Pages

Wednesday, December 21, 2016

Migrating Receive Connectors from Exchange 2010 to 2016 with native Exchange PowerShell cmdlets

I’ve been recently involved with a project where I had to assist a client with a Exchange 2010 to 2016 migration and one of the tasks I was assigned to do was to migrate the existing Exchange 2010 Servers receive connectors to the new Exchange 2016 servers:

image

I’ve come across this quite a few times in the past and even wrote a blog post 6 years ago:

How do I export/import Exchange 2007/2010 receive connectors’ allow relay IPs?
http://terenceluk.blogspot.com/2010/11/how-do-i-exportimport-exchange-20072010.html

It has been awhile since I’ve had to do this so I thought there must be a better way of doing this and what seemed to be the popular solution was this this PowerShell script:

COPY EXCHANGE SERVER RECEIVE CONNECTOR
https://www.granikos.eu/en/justcantgetenough/PostId/209/copy-exchange-server-receive-connector

Unfortunately, the script did not work for me as I would receive the following error when attempting to migrate the Exchange 2010 receive connectors to 2016:

[PS] C:\Scripts>.\Copy-ReceiveConnector.ps1 -SourceServer exhc01 -ConnectorName " Anonymous Relay Connector" -Targ
etServer bmexmb01 -MoveToFrontend -ResetBindings -DomainController dc01.domain.com

Security warning
Run only scripts that you trust. While scripts from the internet can be useful, this script can potentially harm your
computer. If you trust this script, use the Unblock-File cmdlet to allow the script to run without this warning
message. Do you want to run C:\Scripts\Copy-ReceiveConnector.ps1?
[D] Do not run  [R] Run once  [S] Suspend  [?] Help (default is "D"): r
At C:\Scripts\Copy-ReceiveConnector.ps1:116 char:13
+ </a>        <a href="/open-source" class="js-selected-navigation-item nav-item n ...
+             ~
The '<' operator is reserved for future use.
At C:\Scripts\Copy-ReceiveConnector.ps1:118 char:13
+ </a>        <a href="/business" class="js-selected-navigation-item nav-item nav- ...
+             ~
The '<' operator is reserved for future use.
At C:\Scripts\Copy-ReceiveConnector.ps1:120 char:13
+ </a>        <a href="/explore" class="js-selected-navigation-item nav-item nav-i ...
+             ~
The '<' operator is reserved for future use.
At C:\Scripts\Copy-ReceiveConnector.ps1:122 char:11
+ </a>      </nav>
+           ~
The '<' operator is reserved for future use.
At C:\Scripts\Copy-ReceiveConnector.ps1:1736 char:225
+ ... hidden" value="&#x2713;" /></div>
+                    ~
The ampersand (&) character is not allowed. The & operator is reserved for future use; wrap an ampersand in double
quotation marks ("&") to pass it as part of a string.
At C:\Scripts\Copy-ReceiveConnector.ps1:1767 char:11
+       <li>&copy; 2016 <span title="0.10192s from github-fe158-cp1-prd.iad.github ...
+           ~
The ampersand (&) character is not allowed. The & operator is reserved for future use; wrap an ampersand in double
quotation marks ("&") to pass it as part of a string.
At C:\Scripts\Copy-ReceiveConnector.ps1:1767 char:23
+       <li>&copy; 2016 <span title="0.10192s from github-fe158-cp1-prd.iad.github ...
+                       ~
The '<' operator is reserved for future use.
At C:\Scripts\Copy-ReceiveConnector.ps1:1767 char:29
+       <li>&copy; 2016 <span title="0.10192s from github-fe158-cp1-prd.iad.github ...
+                             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unexpected token 'title="0.10192s from github-fe158-cp1-prd.iad.github.net">GitHub</span>' in expression or statement.
At C:\Scripts\Copy-ReceiveConnector.ps1:1767 char:100
+ ... ">GitHub</span>, Inc.</li>
+                    ~
Missing argument in parameter list.
At C:\Scripts\Copy-ReceiveConnector.ps1:1786 char:14
+       You can't perform that action at this time.
+              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The string is missing the terminator: '.
    + CategoryInfo          : ParserError: (:) [], ParseException
    + FullyQualifiedErrorId : RedirectionNotSupported

[PS] C:\Scripts>

image

I did a bit of troubleshooting and searching but could not find a solution so decided to fall back on the same approach in my older blog post using native Exchange PowerShell cmdlets and a bit of editing of the information in notepad.

Before I begin demonstrating the PowerShell cmdlet and switches to use, let’s begin by reviewing the parameters we’ll be configuring for a receive connector by looking at the options in the EAC:

General Options

image

Note that the parameters available to be configured in the screenshot above are:

  • Name
  • Connector status
  • Protocol logging level
  • Maximum receive message size (MB)
  • Maximum local hop count
  • Maximum hop count

These parameters map to the following PowerShell switches:

Parameter Switch

Name

Name

Connector status

Enabled

Protocol logging level

ProtocolLoggingLevel

Maximum receive message size (MB)

MaxMessageSize

Maximum local hop count

MaxLocalHopCount

Maximum hop count

MaxHopCount

Security Options

image

Note that the parameters available to be configured in the screenshot above are:

  • Authentication
  • Permission Groups

These parameters map to the following PowerShell switches:

Parameter Switch Options

Authentication

AuthMechanism

  • Transport Layer Security (TLS)
    • Enable domain security (mutual Auth TLS)
  • Basic authentication
    • Offer basic authentication only after starting TLS
  • Integrated Windows authentication
  • Externally secured (for example, with IPsec)

Permission Groups

PermissionGroups

  • Exchange servers
  • Legacy Exchange servers
  • Partners
    Exchange users
  • Anonymous users

Scoping Options

image

Note that the parameters available to be configured in the screenshot above are:

  • Remote network settings
  • Network adapter bindings
  • FQDN

These parameters map to the following PowerShell switches:

Parameter Switch

Remote network settings

RemoteIPRanges

Network adapter bindings

Bindings

 

FQDN FQDN

Step #1 – Retrieve and Export Receive Connector Configuration

With the configuration parameters outlined above, the first step for migrating the receive connectors to the new Exchange server is to use the Get-ReceiveConnector to export the receive connectors’ information.  The following is the cmdlet with the switches required:

Get-ReceiveConnector -Server <sourceExchangeServerName> | Select Identity,Name,Enabled,ProtocolLoggingLevel,MaxMessageSize,MaxLocalHopCount,MaxHopCount,AuthMechanism,PermissionGroups,RemoteIPRanges,Bindings,FQDN

The cmdlet above will output something similar to the following:

image

Notice that the RemoteIPRanges configuration output gets truncated when the list has more than 16 entries which means if the list has less than 16, you’re set to go but if you have more then you’ll have to execute the following before using the Get-ReceiveConnect cmdlet:

$FormatEnumerationLimit =-1

Get-ReceiveConnector -Server <sourceExchangeServerName> | Select Identity,Name,Enabled,ProtocolLoggingLevel,MaxMessageSize,MaxLocalHopCount,MaxHopCount,AuthMechanism,PermissionGroups,RemoteIPRanges,Bindings,FQDN

image

The cmdlets above will list all of the IPs:

image

Now that we have the cmdlets to export all of the information, proceed to pipe the output to a text file:

$FormatEnumerationLimit =-1

Get-ReceiveConnector -Server <sourceExchangeServerName> | Select Identity,Name,Enabled,ProtocolLoggingLevel,MaxMessageSize,MaxLocalHopCount,MaxHopCount,AuthMechanism,PermissionGroups,RemoteIPRanges,Bindings,FQDN > C:\ReceiveConnectorsExport.txt

image

For the parameter options of the Get-ReceiveConnector cmdlet, refer to the following TechNet article: https://technet.microsoft.com/en-us/library/aa998618(v=exchg.160).aspx

Step #2 – Extract configuration and create new Receive Connector

With the information in the text file we created above, proceed to extract the information, format them properly and use the following cmdlet to create the new receive connector:

New-ReceiveConnector -Name “<NameOfReceiveConnector” -Enabled $true –ProtocolLoggingLevel <verbose or none> –MaxMessageSize <numberMB> -MaxLocalHopCount <number> –MaxHopCount <number> –AuthMechanism <authentication> –PermissionGroups <groups> -RemoteIPRanges x.x.x.x,.x.x.x.x -Bindings 0.0.0.0:25 -FQDN <FQDN for connector> -Server <targetServerName> -TransportRole FrontendTransport

Items to consider for the New-ReceiveConnector cmdlet:

  • You have to remove custom if it is in the PermissionsGroups configuration output
  • You have to add the TransportRole switch with FrontendTransport parameter at the end for Exchange 2013 and 2016 target servers
  • The FQDN may need to change depending on the name used
  • Adjust the bindings IP address if the source configuration uses a specific IP address that is not configured on the target server

For the parameter options of the New-ReceiveConnector cmdlet, refer to the following TechNet article: https://technet.microsoft.com/en-us/library/bb125139(v=exchg.160).aspx

The follow is an example of the cmdlet with parameters:

New-ReceiveConnector -Name “Anonymous Relay Connector” -Enabled $true -ProtocolLoggingLevel verbose -MaxMessageSize 10MB -MaxLocalHopCount 8 -MaxHopCount 60 -AuthMechanism Tls -PermissionGroups AnonymousUsers -RemoteIPRanges 10.21.1.110,10.5.1.3,10.22.1.212,10.22.1.41,10.22.1.68,10.22.1.210,10.22.1.211,10.22.1.157,10.22.1.10,10.22.1.159,10.22.1.25,192.168.60.28,10.34.30.222,10.20.1.75,10.22.1.164,10.23.0.79,10.22.1.37,10.2.1.37,10.22.1.233,10.23.0.19,10.22.1.49,10.34.30.26,10.21.1.142,10.20.1.64,10.43.3.140,192.168.60.172,10.20.1.50,10.21.1.101,10.20.1.83,10.21.1.117,10.23.0.60,192.168.60.158,10.20.1.175,10.21.1.174,192.168.60.162,10.31.30.22,10.23.0.54,10.22.1.51,10.21.1.41,10.20.1.189,10.20.1.162,10.5.8.242,10.21.1.130,10.21.1.10,10.34.10.30,10.5.3.21,10.20.1.174,10.7.3.11,10.7.3.4,10.7.3.8,10.7.3.3,10.20.1.47,10.21.1.111,10.21.1.92,10.22.1.131,10.21.1.26,10.21.1.24,10.21.1.25,10.21.1.23,10.21.1.22,10.34.30.221,10.21.1.51,10.6.3.92,10.6.3.91,10.6.3.53,192.168.60.56,192.168.60.102,10.34.170.60,10.21.1.49,10.34.30.17,10.21.1.48,10.20.1.126,10.20.1.30,10.34.10.11,10.34.10.20,10.34.10.21,10.34.10.10,10.21.1.60,10.21.1.88,192.168.60.58,10.21.1.54,10.20.1.72,10.43.3.80,10.43.3.81,10.21.1.52,10.20.1.181,192.168.60.48,10.20.7.177,192.168.60.183,10.3.2.10,10.20.2.15,192.168.60.127,192.168.60.205,192.168.60.174,192.168.60.104,192.168.60.173,192.168.60.191,10.3.3.203,192.168.60.169,192.168.60.108,192.168.60.55,192.168.170.60,192.168.60.170,192.168.170.30,192.168.60.106,192.168.70.152,192.168.60.198,192.168.60.189,10.3.3.200,192.168.60.185,192.168.70.148,192.168.60.9,192.168.170.125,192.168.170.128,192.168.60.91,192.168.60.148,192.168.170.26,192.168.60.135,192.168.60.24,192.168.60.21,192.168.60.19,192.168.160.136,192.168.60.57,192.168.170.147,192.168.60.8,192.168.60.160,192.168.173.10,192.168.60.124,192.168.160.129,192.168.20.28,192.168.200.0/24,192.168.100.0/24 -Bindings 0.0.0.0:25 -FQDN EXHC01.domain.com -Server bmexmb01 -TransportRole FrontendTransport

image

4 comments:

Kevin W. said...

This was an extremely helpful post for an Exchange 2010 to Exchange 2016 migration. Thank you so much!

Anonymous said...

This is brilliant! Thank you so much

jigga smith said...

This was exactly what I was looking for, thanks!

Anonymous said...

Cool that you found a way to do it, but ran into a similar issue trying to download a script from Github this morning and figured it out... if you right-click the link to the .ps1 file and save it, you're saving a bunch of HTML data as well as the PowerShell script. What I would do is click through to https://github.com/Apoc70/Copy-ReceiveConnector/blob/master/Copy-ReceiveConnector.ps1, copy the raw contents of the file using the little icon on the right, then paste that into Notepad.