Home » Posts tagged 'exchange migrations'

Tag Archives: exchange migrations

Advertisements

Copying Receive Connectors Hither and Yon

If you have done a number of Exchange migrations, or have a large number of servers to migrate in a single migration, I am sure you have run into the pain of replicating the receive connectors to the new server. Lots of settings to copy down and move over plus there is the headache of explicit permissions granted on the connector in the case of relays or other special use connectors. That can waste a lot of time that you would much rather spend on the finale of Sherlock season 3. Let’s see if we can simplify that today with this script for Copy-ReceiveConnector. You call the script as follows:

Copy-Receive Connector -SourceConnector "EXCHANGE\Alternate Receive Connector" -DestinationServer NEWEXCHANGE -DomainController dc01

This will create a new receive connector on the destination server with all of the settings specified on the old receive connector. It will then loop through all of the non-inherited permissions on the connector and copy those over. You can also specify a new name for the connector via -Name. Onto the code.

<# .SYNOPSIS Copy-ReceiveConnector - Copies a receive connector from a source server to a  destination server .DESCRIPTION Takes the source receive connector a creates a copy on the destination server with values populated from the source receive connector. .PARAMETER SourceConnector Identity of the source receive connector .PARAMETER DestinationServer Server name of the destination Exchange server .PARAMETER DomainController Target domain controller for setting the configuration .PARAMETER Name Optional new name for the connector .EXAMPLE Copy-Receive Connector -SourceConnector "EXCHANGE\Alternate Receive Connector"  -DestinationServer NEWEXCHANGE -DomainController dc01 #>
[CmdletBinding()]
param(
[Parameter(Mandatory=$True)][string]$SourceConnector,
[Parameter(Mandatory=$True)][string]$DestinationServer,
[Parameter(Mandatory=$True)][string]$DomainController,
[Parameter(Mandatory=$False)][string]$Name
)
Import-Module ActiveDirectory
# Get the values for the old connector
$Source = Get-ReceiveConnector -Identity $SourceConnector
# Update the name if specified
if($Name)
{
 $Source.Name = $Name
}
# Custom permission group is not allowed in Exchange 2013 so we need to remove it
# Nothing to be concerned about since the ACEs are explicitly copied over.
$TempArray = @($Source.PermissionGroups) -split ", " | Select-String -Pattern "Custom" -NotMatch
$TempString = "$($TempArray)"
$Source.PermissionGroups = $TempString.Replace(" ", ", ")
# Copy all the values over to create the new connector on the 2013 server
New-ReceiveConnector -Bindings $Source.Bindings -Server $DestinationServer -DomainController $DomainController -Name $Source.Name -RemoteIPRanges $Source.RemoteIPRanges -AdvertiseClientSettings $Source.AdvertiseClientSettings -AuthMechanism $Source.AuthMechanism -Banner $Source.Banner -BinaryMimeEnabled $Source.BinaryMimeEnabled -ChunkingEnabled $Source.ChunkingEnabled -Comment $Source.Comment -ConnectionInactivityTimeout $Source.ConnectionInactivityTimeout -ConnectionTimeout $Source.ConnectionTimeout -DefaultDomain $Source.DefaultDomain -DeliveryStatusNotificationEnabled $Source.DeliveryStatusNotificationEnabled -DomainSecureEnabled $Source.DomainSecureEnabled -EightBitMimeEnabled $Source.EightBitMimeEnabled -EnableAuthGSSAPI $Source.EnableAuthGSSAPI -Enabled $Source.Enabled -EnhancedStatusCodesEnabled $Source.EnhancedStatusCodesEnabled -ExtendedProtectionPolicy $Source.ExtendedProtectionPolicy -Fqdn $Source.Fqdn -LongAddressesEnabled $Source.LongAddressesEnabled -MaxAcknowledgementDelay $Source.MaxAcknowledgementDelay -MaxHeaderSize $Source.MaxHeaderSize -MaxHopCount $Source.MaxHopCount -MaxInboundConnection $Source.MaxInboundConnection -MaxInboundConnectionPercentagePerSource $Source.MaxInboundConnectionPercentagePerSource -MaxInboundConnectionPerSource $Source.MaxInboundConnectionPerSource -MaxLocalHopCount $Source.MaxLocalHopCount -MaxLogonFailures $Source.MaxLogonFailures -MaxMessageSize $Source.MaxMessageSize -MaxProtocolErrors $Source.MaxProtocolErrors -MaxRecipientsPerMessage $Source.MaxRecipientsPerMessage -MessageRateLimit $Source.MessageRateLimit -MessageRateSource $Source.MessageRateSource -PermissionGroups $Source.PermissionGroups -PipeliningEnabled $Source.PipeliningEnabled -ProtocolLoggingLevel $Source.ProtocolLoggingLevel -RequireEHLODomain $Source.RequireEHLODomain -RequireTLS $Source.RequireTLS -ServiceDiscoveryFqdn $Source.ServiceDiscoveryFqdn -SizeEnabled $Source.SizeEnabled -SuppressXAnonymousTls $Source.SuppressXAnonymousTls -TarpitInterval $Source.TarpitInterval -TlsDomainCapabilities $Source.TlsDomainCapabilities -TransportRole $Source.TransportRole
# Next we need to copy over all of the explicity created permissions
$ConnectorPermissions = Get-ReceiveConnector -Identity $SourceConnector | Get-ADPermission | where {$_.IsInherited -eq $false}
$ConnectorPermissions | foreach {
 Get-ReceiveConnector "$($DestinationServer)\$($Source.Name)" | Add-ADPermission -DomainController $DomainController -User $_.User -Deny:$_.Deny -AccessRights $_.AccessRights -ExtendedRights $_.ExtendedRights
}

And as a bonus here’s a script for just copying over the permissions configured on a connector, in case you wanted to roll your own connector but didn’t want to spend the time on redefining all of the permissions. Usage is not quite the same as above as you are just specifying a source and destination connector.

Copy-ReceiveConnectorPermissions -SourceConnector "EXCHANGE\Alternate Receive Connector" -DestinationConnector "NEWEXCHANGE\New Receive Connector"
<# .SYNOPSIS Copy-ReceiveConnectorPermissions - Copies the permissions from the source  connector to the destination connector .DESCRIPTION Takes the source receive connector, retrieves all of the explicitly defined  permissions, then applies them to the destination receive connector .PARAMETER SourceConnector Identity of the source receive connector .PARAMETER DestinationConnector Identity of the destination receive connector .EXAMPLE Copy-Receive Connector -SourceConnector "EXCHANGE\Alternate Receive Connector"  -DestinationConnector "NEWEXCHANGE\New Receive Connector" #>
[CmdletBinding()]
param(
[Parameter(Mandatory=$True)][string]$SourceConnector,
[Parameter(Mandatory=$True)][string]$DestinationConnector
)
Import-Module ActiveDirectory
# We need to copy over all of the explicity created permissions
$ConnectorPermissions = Get-ReceiveConnector -Identity $SourceConnector | Get-ADPermission | where {$_.IsInherited -eq $false}
$ConnectorPermissions | foreach {
 Get-ReceiveConnector "$($DestinationConnector)" -DomainController $DomainController | Add-ADPermission -User $_.User -Deny:$_.Deny -AccessRights $_.AccessRights -ExtendedRights $_.ExtendedRights
}
Advertisements

5 Extremely Useful Tools to Simplify your Microsoft Exchange Life

Here’s what I find myself using in my day to day life in working with Exchange. If it weren’t for these then troubleshooting and automation would be a lot more difficult and I would find myself throwing my life away. Why waste time when you could be watching E3 game trailers instead?

  1. PowerShell! This one definitely has to take the first place spot in mention. Not that I have any particular order to how I’m listing everything. If it wasn’t for PowerShell then management of even a single Exchange server would be much more tiresome. Just look at mass creating a number of new users. HR sends you an Excel sheet with all of their details, you save the pertinent bits out to a CSV, then just run it through a little PowerShell script
    $NewUsers = Import-Csv -Path C:\Import\UserList.csv
    foreach($NewUser in $NewUsers)
    {
                    New-Mailbox -Name $NewUser.Name -Password $NewUser.Password -UserPrincipalName $NewUser.UPN -Alias $NewUser.Alias -Database $NewUser.TargetDatabase -DisplayName ($NewUser.FirstName + " " +$NewUser.LastName) -FirstName $NewUser.FirstName -LastName $NewUser.LastName -OrganizationalUnit $NewUser.OU -Phone $NewUser.Phone -ResetPasswordOnNextLogon:$true
    }

    Tada, creating new users has been simplified from hours of manual labor to a few minutes of CSV formatting and scripted importing.

  1. mxtoolbox.com This is a site that gets used often in troubleshooting. I can quickly check on the MX records for any domain including my own, run through a list of BLs to see if my domain is listed, and very importantly run diagnostics on my mail server’s external facing connectors to see what errors may come up. This is where I turn if I don’t have a way to telnet in from the outside. There are a number of other useful tools there as well though they don’t receive as much use as the BL and diagnostics.
  2. testexchangeconnectivity.com A very important site if you are running Exchange migrations. The ActiveSync and Outlook Anywhere tests help greatly for verifying all of your autodiscover functionality and your other CAS services. The Lync tests are great as well if you have that as part of your organization. It is so much easier than having to call up some external user and have them test such and such functionality, again.
  3. migrationwiz.com Speaking of Exchange migrations, I’ve found this particular service to be extremely useful when working with migrations that are not Exchange to Exchange. MigrationWiz will login to the target service and transfer mailboxes to your Exchange server. It is as simple as that. No annoying process of exporting and import PSTs. Furthermore since incremental transfers are available you can spread out your migration without needing to do an overnight cutover.
  4. telnet and nslookup Since these are small I figured I could combine them into one entry. These are also some extremely vital tools in your Microsoft Exchange swiss army knife. I’ve already talked about the usefulness of telnet in previous posts so I won’t bore you all over again. Nslookup is a fantastic way to quickly verify records. Such as comparing your internal DNS records to your external records. Run nslookup autodiscover.contoso.com and nslookup autodiscover.contoso.com 8.8.8.8. The first will check what it is resolving to internally while the second will query Google’s public DNS for the external autodiscover record. MX record lookups are simple as well, nslookup –type=mx contoso.com 8.8.8.8.

Any favorite tools that you find yourself using over and over for your Exchange servers or migrations? Please let me know in the comments.

Mail Queuing for Mail Enabled Public Folders?

Feeling pretty good about yourself you come into the office and sit down to get some work done. After all, someone has to retrieve that Amulet of Yendor so it might as well be you, right? Unfortunately it doesn’t look like today will be your day. The warnings are piling up that your mail queue is getting rather large and some users have been asking where their daily messages in their public folders are. Taking a peek at the queue you see a large and growing number of emails in your Unreachable Domain queue. But your public folder database looks like it is mounted OK. Not cool.

What broke?

This is a fairly common scenario I’ve run into after migrating off of Exchange 2003. Your public folders migrated over successfully and mail had been flowing for a while but as soon as you took down the 2003 server the mail starts queuing up for your mail enabled public folders. Or maybe you went in and started doing some manual cleanup with ADSI Edit. Sometimes even just the uninstall of Exchange 2003 has some unexpected side effects. You remembered to do a backup of your AD prior to that major change, right? There’s a good chance that your public folder hierarchy is missing.

Great, so can we fix this?

The good news is that there is a road to recovery. Let’s check on things first, is your public folder hierarchy actually missing? Pop open the good old Exchange Management Shell and let’s check on a few things.

Import-Module ActiveDirectory
$SearchPath = "CN=Folder Hierarchies,CN=Exchange Administrative Group (FYDIBOHF23SPDLT),CN=Administrative Groups," + (Get-OrganizationConfig).DistinguishedName
Get-ADObject -SearchBase $SearchPath -SearchScope OneLevel -Filter {CN -eq "Public Folders"}

Hopefully you will get a result such as below.

DistinguishedName             Name                          ObjectClass                   ObjectGUID

—————–             —-                          ———–                   ———-

CN=Public Folders,CN=Folde… Public Folders                msExchPFTree                  f6a3cbd4-10e5-452d-9abe-44…

If you get a directory object not found then your public folder hierarchy is missing and we’ll have to recreate it. That’s step one on our way to saving the day. Let’s step back one further and make sure about whether our Folder Hierarchies container is there.

$SearchPath = "CN=Exchange Administrative Group (FYDIBOHF23SPDLT),CN=Administrative Groups," + (Get-OrganizationConfig).DistinguishedName
Get-ADObject -SearchBase $SearchPath -SearchScope OneLevel -Filter {CN -eq "Folder Hierarchies"}

If you get no results then that is missing as well. If you do then at least our container is there and we just need to create the hierarchy. Here’s the bit of PowerShell code that will fix up the missing public folders hierarchy.

<#
.SYNOPSIS
Recreates your public folders hierarchy
.DESCRIPTION
Checks your AD for whether the Folder Hierarchies container exists and the 
Public Folders hierarchy. If one does not exist then it is created.
#>
Import-Module ActiveDirectory

# Build path to the container
$SearchPath = "CN=Exchange Administrative Group (FYDIBOHF23SPDLT),CN=Administrative Groups," + (Get-OrganizationConfig).DistinguishedName
$PFContainer = Get-ADObject -SearchBase $SearchPath -SearchScope OneLevel -Filter {CN -eq "Folder Hierarchies"}

# If it does not exist then create the container
if(!$PFContainer)
{
    New-ADObject -Name "Folder Hierarchies" -Type msExchPublicfolderTreeContainer -Path $SearchPath
    Write-Host "Folder Hierarchies container created."
}
else
{
    Write-Host "Folder Hierarchies container exists already." -ForeGroundColor Yellow
}

# Build path for the public folder tree
$SearchPath = "CN=Folder Hierarchies,CN=Exchange Administrative Group (FYDIBOHF23SPDLT),CN=Administrative Groups," + (Get-OrganizationConfig).DistinguishedName
$PFHierarchy = Get-ADObject -SearchBase $SearchPath -SearchScope OneLevel -Filter {CN -eq "Public Folders"}

# If it does not exist then create it
if(!$PFHierarchy)
{
    New-ADObject -Name "Public Folders" -Type msExchPFTree -Path $SearchPath -OtherAttributes @{msExchPFTreeType="1"}
    Write-Host "Public Folders hierarchy created."
}
else
{
    Write-Host "Public Folders hierarchy already exists." -ForeGroundColor Yellow
}

# Set to our PF hierarchy DN
$PFHierarchy = "CN=Public Folders," + $SearchPath

# DN for our databases
$SearchPath = "CN=Databases,CN=Exchange Administrative Group (FYDIBOHF23SPDLT),CN=Administrative Groups," + (Get-OrganizationConfig).DistinguishedName
$PFDatabases = Get-ADObject -SearchBase $SearchPath -SearchScope OneLevel -Filter {objectClass -eq "msExchPublicMDB"}

# Grab all of the public folder databases and loop through them
if($PFDatabases)
{
    foreach($PFDatabase in $PFDatabases)
    {
        $PFDatabase.msExchOwningPFTree = $PFHierarchy
        Set-ADObject -Instance $PFDatabase
        Write-Host "Fixed database $($PFDatabase.Name)"
    }
}
# Or if no public folder databases exist you have further problems ...
else
{
    Write-Host "No Public Folder Databases found." -ForeGroundColor Yellow
}

But you’ll find that your work is not quite done yet. Your public folders are missing their homeMDB. Or this could have been your problem all along without any need to recreate the public folder hierarchy. You can verify this as the problem with this quick search:

$PFPath = "CN=Public Folders,CN=Folder Hierarchies,CN=Exchange Administrative Group (FYDIBOHF23SPDLT),CN=Administrative Groups," + (Get-OrganizationConfig).DistinguishedName
$SearchBase = "CN=Microsoft Exchange System Objects," + (Get-ADRootDSE).rootDomainNamingContext 
Get-ADObject -SearchBase $SearchBase -SearchScope OneLevel -Filter { (homeMDB -notlike "*") -and (ObjectClass -eq "publicFolder")}

If you don’t see anything then you know that your mail enabled public folders are fine. But most likely you’ll get a few results. To quickly fix those up run through this script.

<#
.SYNOPSIS
Fix any missing homeMDB attributes on public folders.
.DESCRIPTION
The script runs an LDAP search for all mail enabled public folder objects and
sets the homeMDB attribute to the LDAP path to your public folder hierarchy.
.NOTES
The script needs to be run in all domains requiring the fix.
#>
Import-Module ActiveDirectory
# Build the DN to the public folders hierarchy
$PFPath = "CN=Public Folders,CN=Folder Hierarchies,CN=Exchange Administrative Group (FYDIBOHF23SPDLT),CN=Administrative Groups," + (Get-OrganizationConfig).DistinguishedName
# Build the DN to the public folder objects
$SearchBase = "CN=Microsoft Exchange System Objects," + (Get-ADRootDSE).rootDomainNamingContext
# Search for all PFs with a blank homeMDB
$TargetPFs = Get-ADObject -SearchBase $SearchBase -SearchScope OneLevel -Filter { (homeMDB -notlike "*") -and (ObjectClass -eq "publicFolder")}

# Fix all of the public folders
if($TargetPFs)
{
  foreach($TargetPF in $TargetPFs)
  {
    Write-Host "Fixing $($TargetPF.Name)"
    $TargetPF.homeMDB = $PFPath
    Set-ADObject -Instance $TargetPF
  }
}
# Good news (maybe), no public folders that require fixing
else
{
  Write-Host "No public folders missing homemdb."
}

Fantastic, are we done yet?

Nearly! Just give the mail queues a kick and you should see the emails quickly flushing out into your public folder databases. Now you can get back to your day of NetHack knowing that all is well with the world once again.

The Number One Easy Way to Setup a Failed Migration

It surprises me how much I run across this one but then again I have been guilty of it as well.

Eater of backups

I eat backups! Garr!

There is a very important first step that I find skipped over and forgotten quite often when it comes to running an Exchange migration. Or really any other kind of migration. Have you taken a system state backup of AD yet? No? Then you’re just spinning the bottle and hoping it doesn’t end up with you getting cozy with Microsoft’s support hoping that they can fixed your screwed up Active Directory.

Don’t make the mistake of assuming backups are working

I made this mistake once upon a time. It was from one of the first Exchange migrations I was running. I didn’t feel like being bothered to take a backup of AD as the server was a really slow server. I was confident that the nightly backups had taken care of everything anyhow. Though I didn’t bother to validate this. So I went directly into running the migration and everything was going smoothly at first. Everything looked like it was running great. But then part of the way through I found that AD replication had broken and that it possibly had been that way for a while. It would have been easy to roll back to an AD backup, correct the problem and then retrace my steps but unfortunately that wasn’t an option. Because I hadn’t taken a backup. The nightly backups hadn’t worked in several months either. That lead into a call with Microsoft later on and then having to spend even more hours fixing things manually via ADSIedit when they couldn’t figure it out.

I don’t want to be the one cleaning up after you

It is a very simple step to take at the very beginning. Just grab a backup before you run your first setup.com /PrepareAD. While you’re at it, why don’t you test the backup of your current mail server and make sure that it is working ok as well. Trust me on this. You don’t want to be the guy to explain to your boss that the data is gone as your only valid backup is from 3 years ago. Your backups are working, right? You might want to double check on that just to be sure. I recommend a mock restore for that extra bit of assurance.

Exchange 2007 Single Server Migrations for Profit or Headache

I was originally writing up a guide for migrating, actually transitioning, Exchange 2003 to Exchange 2007. There are lots of guides out there that would have better screenshots and perhaps even better written steps. Basically I would not really be meeting a need as there are already plenty out there doing so. So instead I am scrapping all of my original work and concentrating on issues that I believe are not talked about as much out there. Mostly these issues affect those that are doing single server migrations, which is basically you have one Exchange 2007 server holding all of your roles. They have caused me a great deal of headache and drama which I am sure is true for others doing such migrations as well. I would imagine that this is mostly the SMB sector, which is where the majority of my work in this is being done. Let’s talk about the biggest issue now, client access.

The CAS role plays a big part in your Exchange organization as it is the broker for all requests to your mailboxes. You will have MAPI requests as well as HTTPS, POP3 and others coming into this server. By the way as a security side note the recommended set up is to have your CAS role on your internal network with a reverse proxy in your DMZ for proxying requests through to your CAS. The CAS when it receives a request for a mailbox that resides on a 2003 servers proxies that request through to your 2003 server. No issues at all there. The problem that comes up, though, with having a CAS on the same server as your MB is that web requests no longer get proxied to your 2003 servers, they get redirected. This is due to davex.dll handling the requests on a mailbox server, and it will grab the requests first. Exprox.dll is what handles proxying. This redirection is not configurable either. So that causes a problem when it is redirecting an external request to an internal FQDN. That doesn’t work out too well and you get lots of angry OWA users wondering why their logins take them to an invalid address. For a more in depth explanation take a look here. Let’s take a look at a few ideas for mitigating this issue.

First off an easy fix would be to make sure your Exchange 2003 FQDN has a matching public address. This is not a recommended set up though at all. It is against best practices to have your internal domain match your external domain. Not to mention you can get a number of funny DNS issues going on if this is the case unless you’ve planned things out well. Read this article for some more DNS information, and especially look at the split-brain section. All of this can turn your easy fix into a much more complicated fix. If the stars do just happen to be right on your migration though, then go for this. Set up a public record matching your internal Exchange 2003 name and you’ll be set. This will be transparent to your users.

Next up would be to use a reverse proxy such as ISA 2006. This would be great as it keeps the strict definitions of your DMZ as it keeps your Exchange servers from having to blur the lines. This doesn’t seem to be something that most SMBs care about in my experience though. They don’t seem to see the need for security and how having a properly defined DMZ fits into this. But that goes into an entirely separate article and could sound a bit ranty.

Other methods will require a bit more cooperation from your users. Remember, in Exchange 2007 the OWA access by default is /owa. So you will need to communicate this to your users as you migrate their mailboxes over. Then, remove the /exchange virtual directory through the Exchange Shell and recreate it in IIS. Finally, set up /exchange with a custom 403 redirect to a different port on your external address. Mind you that you’ll need to make sure that port does point to your legacy server. This either requires your firewall to be able to do port translation or changing the ports on your 2003 server.

Finally, and the most recommended method, is to set up a temporary virtual machine that will purely host a CAS role. Then everything will be proxied as it is supposed to be. The down side to this is that it would require a separate license in which case you might as well plan for as separate CAS to begin with.

Fortunately as long as everything is configured properly Outlook Anywhere and ActiveSync seem to work just fine. Some dangers with those is if you are having some DNS issues internally or improper communication with a global catalog. This can add to your headache so you will want to cozy up to rcpping which you can grab from Microsoft and get more info about how to work it from here. Another great site I have recently found out about is the Remote Connectivity Analyzer. This site will enable you to test Outlook Anywhere, ActiveSync, SMTP and Autodiscover with detailed error messages about where these break down. It will become your best friend very swiftly.

I guess the moral of all these suggestions is to make sure you have your migration well planned out. Run it through a test lab first if you are able. Definitely make sure you test it out, and definitely don’t spring it on your users unawares. You could be in for quite a “fun” surprise.

%d bloggers like this: