上次用 Let's Encrypt 佈署 Remote Desktop Gateway 後, 這次要來佈署 Exchange 2016
Updated:
2025.02.24Let's Encrypt 已經改用 https://www.win-acme.com/PowerShell Script 更新加入 Exchange Online Hybrid 的部分 (TLS Issuer Name)
採用的版本是 LetsEncryptWinSimple.v1.9.11.2 (直接下載連結)
解壓縮後我把他放到 Exchange Server 的 C:\Cert\LetsEncryptWinSimple.v1.9.11.2 路徑
接著執行 letsencrypt.exe
這裡我選 M
這裡我選 4 , 因為要輸入多個 FQDN
接著輸入連接 Exchange 用的主要 FQDN: webmail.contoso.com
以及 Auto Discover 用的 FQDN: autodiscover.contoso.com
選擇以 webmail.contoso.com.tw 為憑證的主要 FQDN
選擇驗證方式, 這裡我選 3 將驗證檔案放到指定的路徑去
指定的路徑放到 IIS 的 Root 去
順便讓他自己幫我們設定好 web.config
然後在驗證成功取得憑證後不需要自動 Run 任何 Script
在上面這張圖片按下 Enter 之前, 有一些動作必須要先完成
安裝 Exchange 2016 後 IIS 預設不會接受 HTTP 無加密的連線, 只接受 HTTPS
所以為了要讓 Let's Encrypt 能透過 HTTP 的方式驗證我們的合法性
必須先將 HTTP 打開
到 IIS 主控台 -> Default Web Site 點選右邊的 SSL Settings
把 Require SSL 的勾勾拿掉 (要到憑證後記得要勾回來)
之後按下 Enter, 經過一些連線驗證後就可以取得憑證了
憑證會放在 C:\ProgramData\win-acme\httpsacme-v01.api.letsencrypt.org
下圖當然不會成功了, 因為範例寫 contoso.com
Auto Renew 的部份:
$OldPublishedURL = "webmail.contoso.com"
$NewPublishedURL = "webmail.contoso.com"
$CertPassword = "P@##w0rd"
$ExchangeServer = $("EX-01","EX-02")
$Domain = "Contoso.com"
$WACSPath = "C:\Cert\"
$WACSEXEFileName = "wacs.exe"
$PFXPath = "C:\Cert\Cert\"
# For Exchange Online Hybrid
$RenewConnectorTLSCertificateName = $True;
cd $WACSPath
$DateTimeString = Get-Date -format yyyyMMdd_HHmmss
$TranscriptLog = (Get-Item -Path ".\" -Verbose).FullName + "\Logs\" + ("CertRenew_" + $DateTimeString + ".log")
start-transcript -path $TranscriptLog
write-host ""
write-host "*** Cert Renew"
write-host ""
Import-Module IISAdministration
$ConfigSection = Get-IISConfigSection -SectionPath "system.webServer/security/access" -Location "Default Web Site"
Set-IISConfigAttributeValue -AttributeName sslFlags -AttributeValue None -ConfigElement $ConfigSection
$IISDir = Set-WebConfigurationProperty -Location "Default Web Site/.well-known" -Filter 'system.webserver/security/access' -name "sslFlags" -Value None
$IISDirCeck = (Get-WebConfigurationProperty -Location "Default Web Site/.well-known" -Filter 'system.webserver/security/access' -name "sslFlags").Value
# Remove Firewall Rule Blocking TCP 80 for Let's Encrypt Authentication
$FWGroupName = "CertTools";
$Remove = New-NetFirewallRule -DisplayName "RemovePrepare" -Group $FWGroupName -Direction "inBound" -Program "C:\windows\system32\calc.exe" -Action Block -RemoteAddress $BlockIPs
Remove-NetFirewallRule -Group $FWGroupName -Confirm:$False
# Remove Firewall Rule Blocking TCP 80 for Let's Encrypt Authentication
$CommandLine = "$WACSPath$WACSEXEFileName --renew --baseuri ""https://acme-v02.api.letsencrypt.org/"""
cmd /c $CommandLine
# Add Firewall Rule Back for Blocking TCP 80
$BlockIPs = @("0.0.0.1-9.255.255.255", "11.0.0.0-172.15.255.255", "172.32.0.0-192.167.255.255", "192.169.0.0-255.255.255.255")
New-NetFirewallRule -DisplayName "Block 80 Port inBound" -Group $FWGroupName -Direction "inBound" -Protocol "TCP" -LocalPort 80 -Action Block -RemoteAddress $BlockIPs
# Add Firewall Rule Back for Blocking TCP 80
$ConfigSection = Get-IISConfigSection -SectionPath "system.webServer/security/access" -Location "Default Web Site"
Set-IISConfigAttributeValue -AttributeName sslFlags -AttributeValue Ssl -ConfigElement $ConfigSection
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.SnapIn;
$PFXFullPath = ($PFXPath + ($NewPublishedURL -Replace '\*','_') + ".pfx")
$NewCertProperties = (Get-PfxData -FilePath $PFXFullPath -Password (ConvertTo-SecureString -String $CertPassword -Force -AsPlainText)).EndEntityCertificates | Select Thumbprint,NotAfter
$LastCerts = Get-ExchangeCertificate | where {$_.Subject -eq "CN=$OldPublishedURL"} | select Thumbprint,NotAfter
$LastCertProperties = $NewCertProperties;
foreach ($LastCert in $LastCerts) {
if ($LastCert.Thumbprint -ne $NewCertProperties.Thumbprint) {
$LastCertProperties = $LastCert;
};
};
$NewCertThumbprint = $NewCertProperties.Thumbprint
$NewCertNotAfter = $NewCertProperties.NotAfter
$LastCertThumbprint = $LastCertProperties.Thumbprint
$LastCertNotAfter = $LastCertProperties.NotAfter
write-host
write-host "New Cert Thumbprint is: $NewCertThumbprint"
write-host "New Cert NotAfter is: $NewCertNotAfter"
write-host
write-host "Last Cert Thumbprint is: $LastCertThumbprint"
write-host "Last Cert NotAfter is: $LastCertNotAfter"
write-host
if ( ($NewCertNotAfter -lt $LastCertNotAfter) -or ($NewCertNotAfter -eq $LastCertNotAfter) ) {
write-host "New Cert's ExpireDate is Less than or Equal to the old one, Please check."
Stop-Transcript
exit;
}
if ($NewCertThumbprint -eq $LastCertThumbprint) {
write-host "Cert Doesn't Change, Program Close, Please check."
Stop-Transcript
exit;
}
write-host ""
write-host "*** Backup New Cert With Date"
write-host ""
Get-ChildItem -Path $PFXFullPath | Copy-Item -Destination $PFXFullPath.Replace(".pfx","_Expired_$($($NewCertProperties.NotAfter).tostring("yyyyMMdd")).pfx") -Force -Confirm:$false
write-host ""
write-host "*** Copy New Cert to Other Servers"
write-host ""
foreach ($ExServer in $ExchangeServer) {
if ($ExServer -ne $Env:ComputerName) {
write-host Copy Item from $PFXPath to \\$ExServer.$Domain\$($PFXPath.Replace(":","$"))
Get-ChildItem -Path $PFXPath | Copy-Item -Destination "\\$ExServer.$Domain\$($PFXPath.Replace(":","$"))" -Force -Confirm:$false
};
};
write-host ""
write-host "*** Import New Cert"
write-host ""
$CommandLine = 'C:\Windows\System32\certutil.exe -f -p "' + $CertPassword + '" -importpfx "'+$PFXFullPath+'" NoExport'
cmd /c $CommandLine
write-host ""
write-host "*** Enable New Cert on Exchange"
write-host ""
Enable-ExchangeCertificate -Thumbprint $NewCertThumbprint -Services POP,IMAP,IIS,SMTP -Force -Confirm:$false -ErrorAction Stop
Get-ExchangeCertificate | Format-List FriendlyName,Subject,CertificateDomains,Thumbprint,Services
Import-Module WebAdministration
$IISSSLBindings = Get-ChildItem IIS:SSLBindings
$BackEndWebCertThumbprint = ($IISSSLBindings | where {$_.Sites.Value -eq 'Exchange Back End'}).Thumbprint;
write-host ('BackEnd Web Cert: ' + $BackEndWebCertThumbprint)
$BackEndWebCertThumbprint
if ( ($BackEndWebCertThumbprint) -ne $NewCertThumbprint ) {
(((Get-ChildItem IIS:\Sites) | where {$_.Name -eq 'Exchange Back End'}).Bindings.Collection | where {$_.protocol -eq 'https' -and $_.bindingInformation -eq '*:444:'}).AddSslCertificate($NewCertThumbprint, "My")
write-host ('Update BackEnd Web Cert: ' + $NewCertThumbprint)
};
write-host ""
write-host "*** Reset IIS"
write-host ""
iisreset
# Section for Exchange Online Hybrid
if ($RenewConnectorTLSCertificateName -eq $True) {
write-host ""
write-host "*** Renew ReceiveConnector and SendConnector TLSCertificateName"
write-host ""
$TLSCert=Get-ExchangeCertificate $NewCertThumbprint
$TLSCertname="<I>$($TLSCert.Issuer)<S>$($TLSCert.Subject)"
# ----------
$ExchangeFrontendServer = ( $Env:ComputerName + '\Default Frontend ' + $Env:ComputerName);
$NewReceiveConnectorTLSCertificateName = $TLSCertname;
$LastDefaultReceiveConnectorTLSCertificateName = (Get-ReceiveConnector $ExchangeFrontendServer | select TLSCertificateName).TLSCertificateName;
write-host ('New Default ReceiveConnector TLSCertificateName : ' + $NewReceiveConnectorTLSCertificateName);
write-host ('Last Default ReceiveConnector TLSCertificateName: ' + $LastDefaultReceiveConnectorTLSCertificateName);
write-host ""
write-host "*** Remove Last Cert"
write-host ""
if ($LastCertThumbprint -ne $Null) {
Get-ChildItem -Path "Cert:\LocalMachine\My" | where {$_.Thumbprint -eq $LastCertThumbprint} | Remove-Item -Confirm:$false
};
Set-ReceiveConnector -Identity $ExchangeFrontendServer -TLSCertificateName $TLSCertname
# ----------
$ClientFrontendServer = ( $Env:ComputerName + '\Client Frontend ' + $Env:ComputerName);
$LastClientReceiveConnectorTLSCertificateName = (Get-ReceiveConnector $ClientFrontendServer | select TLSCertificateName).TLSCertificateName;
write-host ('New Client ReceiveConnector TLSCertificateName : ' + $NewReceiveConnectorTLSCertificateName);
write-host ('Last Client ReceiveConnector TLSCertificateName: ' + $LastClientReceiveConnectorTLSCertificateName);
Set-ReceiveConnector -Identity $ClientFrontendServer -TLSCertificateName $TLSCertname
# ----------
Get-SendConnector | Where {$_.Identity -like "Outbound to Office 365*"} | Set-SendConnector -TLSCertificateName $TLSCertname
Restart-Service MSExchangeTransport
};
# Section for Exchange Online Hybrid
Get-ExchangeCertificate | Format-List FriendlyName,Subject,CertificateDomains,Thumbprint,Services,NotAfter
Stop-Transcript
exit;
您好方便請教以下訊息:
回覆刪除[WARN] Invalid SiteId '', should be a number
[WARN] No valid sites selected
[EROR] NullReferenceException: 並未將物件參考設定為物件的執行個體。
請問該如何修正呢?誠摯感謝