Hardware used during the installation:
- a VM on XEN Server 8.1
- CPU: AMD EPYC 7402P 24-Core Processor – 4 core then switch to 8 core when switching to production
- Memory: 32 Gbytes then switch to 48 Gbytes when moving to production
- System drive: SSD with 80 Gbytes and 52 Gbytes used by the system
- Data drive: SSD with 500 Gbytes used by exchange database and log files
- The size of all databases and transaction logs are around 400GB. (as reference) when planning
Pre-requirement infrastructure
- Domain forest minimum: Windows Server 2012 R2 Standard or Datacenter
- Coexistence during the migration: Supported with Exchange 2013 Cumulative Update 21 (CU21) or later on all Exchange 2013 servers in the organization, including Edge Transport servers. Supported with Exchange 2016 CU11 or later on all Exchange 2016 servers in the organization, including Edge Transport servers
- Operating system: Windows Server 2019 Standard or Datacenter
- Exchange support only TLS 1.2 natively
- All operating system since Windows 8.1 support it and you don’t need to enable TLS 1.0 or TLS 1.1 in regedit
- If you have Windows 7 or Windows 8, then follow the link to enable the support of TLS 1.2
- Enable TLS 1.1 and TLS 1.2 on Windows 7 and Windows 8
Pre-requirement software
- .NET Framework 4.8
- Visual C++ Redistributable Package for Visual Studio 2012
- Visual C++ Redistributable Package for Visual Studio 2013
Pre-requirement lync or Skype for Business server components, if needed
- Install the Server Media Foundation windows feature by executing the following command in Windows PowerShell:
PowerShell: Install-WindowsFeature Server-Media-Foundation - Install Unified Communications Managed API 4.0. This package is available for download and in the \UCMARedist folder on the Exchange Server media.
System pre-requirement: Windows components
- Desktop Experience
- PowerShell: Install-WindowsFeature Server-Media-Foundation, NET-Framework-45-Features, RPC-over-HTTP-proxy, RSAT-Clustering, RSAT-Clustering-CmdInterface, RSAT-Clustering-Mgmt, RSAT-Clustering-PowerShell, WAS-Process-Model, Web-Asp-Net45, Web-Basic-Auth, Web-Client-Auth, Web-Digest-Auth, Web-Dir-Browsing, Web-Dyn-Compression, Web-Http-Errors, Web-Http-Logging, Web-Http-Redirect, Web-Http-Tracing, Web-ISAPI-Ext, Web-ISAPI-Filter, Web-Lgcy-Mgmt-Console, Web-Metabase, Web-Mgmt-Console, Web-Mgmt-Service, Web-Net-Ext45, Web-Request-Monitor, Web-Server, Web-Stat-Compression, Web-Static-Content, Web-Windows-Auth, Web-WMI, Windows-Identity-Foundation, RSAT-ADDS
- Disable IPv6 because it will not be used and make sure it’s not used on receive connectors after installing Exchange
Installing Microsoft Exchange 2019 server
Enter the product key from exchange powershell
- Set-ExchangeServer Mailbox01 -ProductKey 12345-12345-12345-12345-12345
Delete the default exchange certificate and add a third part certificate
- Open mmc.exe and add snap-in certificates
- Delete the Friendly Name “Microsoft Exchange”
- Enable third party certificate on exchange smtp service using its Thumbprint
- Start Exchange powershell on the server
- Run: Get-ExchangeCertificate
- Find the correct Thumbprint certificate
- Run: Enable-ExchangeCertificate 700AD1C6BEC29AB997806652BAC4513315D49285 -Services SMTP
Allow Exchange to send mails outside
- Open Exchange Admin Center: https://SERVERNAME/ecp/?ExchClientVer=15
- mail flow -> send connectors
- Select the connector used to send mails and add your new server to the scoping (source server)
Create additional database on your exchange
- Depend on the version of your exchange, standard or enterprise. you can create maximum 5 database or unlimited for enterprise
- Create a folders structure on your additional drive for all your data files and log files
- On Exchange Admin Center
- Open: Servers -> Databases
- Click on “+” symbol
- Run: iisreset from command prompt to restart IIS
- Use “…” to mount the database.
Move Arbitration mailbox from default mailbox database
- Check the name of the default mailboxdatabse by running from exchange powershell:
Get-MailboxDatabase - Check if the server have any system mailbox ( AuditLog, Archive, Arbitration, Monitoring)
- Get-MailBox -server SRVERNAME -Arbitration
- Move the default mailbox to the new mailbox database
- Get-Mailbox -server SERVERNAME -AuditLog | New-MoveRequest -TargetDatabase “System_DB001”
- Check if the moved mailbox is complete
- Get-MoveRequest | Get-MoveRequestStatistics
- Delete completed move request:
- Get-MoveRequest -movestatus completed | remove-moverequest
- Delete the default database after moving all system mailbox
- Remove-MailboxDatabase -Identity “Mailbox Database 1067783753”
- After deleting the database, restart Microsoft Exchange Mailbox Replication service
Moving mailboxes from previous exchange 2013 or 2016 to the new exchange
- Tune the slow migration speed of mailboxes
- Open a file below in notepad.exe
- C:\Program Files\Microsoft\Exchange Server\V15\Bin\MsExchangeMailboxReplication.exe.config
- Add: ExportBufferSizeOverrideKB=”7500″ under ExportBufferSizeKB
- Update: ExportBufferSizeKB=”512” to ExportBufferSizeKB=”10240″
- Update: MaxActiveMovesPerSourceMDB=”20” to MaxActiveMovesPerSourceMDB=”50″
- Update: MaxActiveMovesPerTargetMDB=”20” to MaxActiveMovesPerTargetMDB=”50″
- Example of moving mailbox
- New-MoveRequest -Identity user01@domain.com -TargetDatabase “System_DB001” -Priority Emergency -BadItemLimit 10
- New-MoveRequest -Identity user02@domain.com -TargetDatabase “System_DB001” -Priority Emergency -BadItemLimit 10
- New-MoveRequest -Identity user02@domain.com -TargetDatabase “System_DB001” -Priority Emergency -BadItemLimit 10
- Check the status: Get-MoveRequest | Get-MoveRequestStatistics
- Remove the completed: Get-MoveRequest -movestatus completed | remove-moverequest
- Move Public Folder. if available
- Get-Mailbox -PublicFolder | New-MoveRequest -TargetDatabase PublicFolder_DB001 -Priority Emergency -BadItemLimit 10
- Move Arbitration mailboxes from the previous exchange server database before delete them
- Check if you don’t have any extra mailbox like rooms in the previous database
- Get-MailboxDatabase OLD_Exchange_DB001 | Get-Mailbox | New-MoveRequest -Priority Emergency -BadItemLimit 10
- All the databases from the previous exchange need to be empty, otherwise you will not be able to delete it from Exchange Admin Center
- Delete the databases from the previous exchange server and then delete exchange from the servers, to clean all records about previous exchange from Active directory
Create Database Availability Groups (DAG)
- Install failover cluster on all member servers (the members of the cluster must (should) have the same operating system)
- Prestage Cluster Name object (CNO)
- Open Active Directory Users and Computers
- Create a new computer in Computers OU:
- Enable Active Directory Advanced features
- Open the properties of the new computer object and select Security tab
- Add all servers which you are planning to make members of the DAG (exchange servers)
- Give a full right to the members of the DAG
- Switch to “Member Of” tab
- Make sure it is member of “Exchange Trusted Subsystem” or add it
- Finally, Disable the computer account.
- Create the DAG on Exchange Admin Console -> Servers -> database availability groups
- The name of DAG in the picture above should be the same like the computer name created early
- The Witness server, guarantees that a Quorum is preserved in the cluster. Two exchange servers must be available in any time, if you have to reboot one of them (in our labs we use two servers), with witness server (which is a small share will keep exchange accessible while one of them is down.
- Witness directory is the local shared directory on the network of Witness server
- DAG IP, is an IP which will be added automatically to the active exchange server while the second one is running as passive server or offline for some reason
- Add the servers to the new created DAG
- Click on the database and select
- On the second server, create the same path structure folders like in the first server
- Select a database and click on “…” to “Add database copy” like in the picture below
- Exchange will create a copy of the database and transaction logs on the second server automatically (if the path on both servers are the same). in our labs
- EDB folder: D:\Exchange Database\System_DB001\EDB
- Transaction log: D:\Exchange Database\System_DB001\T_Logs
Enable circular logging
- On each database, enable circular logging in order to save space of your DATA volume where the databases are located (if needed)
Enable Exchange Anti-Spam on each exchange server
- Check transport agent before installation using powershell: Get-TransportAgent
- On powershell run: C:\Program Files\Microsoft\Exchange Server\V15\Scripts>.\install-AntispamAgents.ps1
- Run: Get-TransportAgent, to see the difference
- Set-ContentFilterConfig -Enabled $true
- Set-SenderFilterConfig -Enabled $true
- Set-SenderIDConfig -Enabled $true
- Set-SenderReputationConfig -Enabled $true
- Restart “Microsoft Exchange Transport” service
Update Virtual Directory URL
- Make sure the server name, InterlanURL and ExternalURL are changed before running the commands
Get-EcpVirtualDirectory -Server SERVERNAME | Set-EcpVirtualDirectory -InternalUrl https://servername.domain.local/ecp -ExternalUrl https://mail.domain.com/ecp Get-WebServicesVirtualDirectory -Server SERVERNAME | Set-WebServicesVirtualDirectory -InternalUrl https://servername.domain.local/EWS/Exchange.asmx -ExternalUrl https://mail.domain.com/EWS/Exchange.asmx Get-MapiVirtualDirectory -Server SERVERNAME | Set-MapiVirtualDirectory -InternalUrl https://servername.domain.local/mapi -ExternalUrl https://mail.domain.com/mapi Get-ActiveSyncVirtualDirectory -Server SERVERNAME | Set-ActiveSyncVirtualDirectory -InternalUrl https://servername.domain.local/Microsoft-Server-ActiveSync -ExternalUrl https://mail.domain.com/Microsoft-Server-ActiveSync Get-OabVirtualDirectory -Server SERVERNAME | Set-OabVirtualDirectory -InternalUrl https://servername.domain.local/OAB -ExternalUrl https://mail.domain.com/OAB Get-OwaVirtualDirectory -Server SERVERNAME | Set-OwaVirtualDirectory -InternalUrl https://servername.domain.local/owa -ExternalUrl https://mail.domain.com/owa Get-PowerShellVirtualDirectory -Server SERVERNAME | Set-PowerShellVirtualDirectory -InternalUrl http://servername.domain.local/powershell -ExternalUrl http://mail.domain.com/powershell Get-ClientAccessService -Identity SERVERNAME | Set-ClientAccessService -AutoDiscoverServiceInternalUri https://servername.domain.local/Autodiscover/Autodiscover.xml Get-AutodiscoverVirtualDirectory -Server SERVERNAME | Set-AutodiscoverVirtualDirectory -InternalUrl https://servername.domain.local/autodiscover/autodiscover.xml -ExternalUrl https://mail.domain.com/autodiscover/autodiscover.xml Get-OutlookAnywhere -Server SERVERNAME | Set-OutlookAnywhere https://servername.domain.local -ExternalUrl https://mail.domain.com Set-OutlookProvider EXPR –CertPrincipalName msstd:mail.domain.com Set-OutlookProvider EXCH –CertPrincipalName msstd:mail.domain.com Set-OutlookProvider WEB –CertPrincipalName msstd:mail.domain.com
Configure Autodiscover on Internal and External DNS servers
On outside DNS configure an A-record which point to our outside IP addresses of our Exchange servers and then add an SRV-record
- Add the A-records “mail” on outside DNS domain name. (in our lab it’s domain.com)
- Add an SRV-record pointing to mail.domain.com
On internal Active Directory server, we will add a zone mail.domain.com and add to it the IP address used while configuring our DAG “192.168.0.23” or create A-record “mail” in our local zone “domain.local” which point to our DAG IP address and then add an SRV record.
- Add an SRV-record
- Depend on the method used (new zone or A-record on your local domain zone) make sure the record on “the host offering this service” is correct. in our lab we create a new zone mail.domain.com
Update IIS binding
Update the IIS on each exchange server and make sure you add new bind to host name mail.domain.com and map it to a correct SSL certificate
Enable Strict-Transport-Security
- Name: Strict-Transport-Security
- Value: max-age=31536000
Protect Exchange OWA from Brute-Force attack
- Open Regedit on Exchange CAS server.
- Go to HKLM\SYSTEM\CurrentControlSET\Services\InetInfo\Parameters
- Create a new DWORD with a name UserTokenTTL and keep the value 30 (this means keeping the Cache only for 30 Sec)
Clean log files from system drive
- Clear Exchange 2013/2016/2019 Log & ETL Files
- Use the powershell script and create a scheduled task to run the script daily with high privelege
Move mail.que and IPFilter database from system drive
- Automatic: (recommended to reuse mail.queue DB and not lost data)
- [PS] C:\Program Files\Microsoft\Exchange Server\V15\scripts>.\Move-TransportDatabase.ps1 -queueDatabasePath ‘Q:\TransportRoles\data\Queue’ -queueDatabaseLoggingPath ‘Q:\TransportRoles\data\Queue’ -iPFilterDatabasePath ‘Q:\TransportRoles\data\IpFilter’ -iPFilterDatabaseLoggingPath ‘Q:\TransportRoles\data\IpFilter’ -temporaryStoragePath ‘Q:\TransportRoles\data\Temp’
- Manual
- to save space on system drive, it’s better to move mail.que database to alternative drive in the same way like we do for exchange mailbox databases
- edit: C:\Program Files\Microsoft\Exchange Server\V15\Bin\EdgeTransport.exe.config
<add key=”QueueDatabasePath” value=”D:\Exchange Database\Exchange Queue\Database” />
<add key=”QueueDatabaseLoggingPath” value=”D:\Exchange Database\Exchange Queue\Logs” />
<add key=”IPFilterDatabasePath” value=”D:\Exchange Database\IPFilter\Database” />
<add key=”IPFilterDatabaseLoggingPath” value=”D:\Exchange Database\IPFilter\Logs” />
Restart “Microsoft Exchange Transport” service
Enable the Password Reset Option
Log in to exchange server with your admin credentials.Open PowerShell with administrative privileges and execute the following three commands.
- Add-pssnapin microsoft*
- Install-CannedRbacRoles
- Install-CannedRbacRoleAssignments
- Log in to the Exchange Admin Center and click on Permissions.
- Right-click ‘Organization Management’ and then click Edit.
- Click the ‘+’ sign on the roles section.
- Select ‘Reset Password’ and then click Add. Click OK and then click Save.
- Log out from the Exchange Admin Center.
- When you log in again to the Exchange Admin Center and open any existing user mailbox properties, you should see the reset password option.
Configure Kerberos authentication with Exchange 2019
Restrict ECP access
Save Sent Items in Shared Mailbox Sent Items folder
Get-Mailbox info@example.net | set-mailbox -MessageCopyForSentAsEnabled $True
or
Get-Mailbox info@example.net | set-mailbox-MessageCopyForSendOnBehalfEnabled $True