2019-01-30

IIS Reverse Proxy with HTTPS over SSL Cert + Auto Renew IIS Site Binding Let's Encrypt by Powershell

原本的網站沒有走 https 且很難處理
故利用前端 IIS + ARR 來做 Reverse Proxy with HTTPS over SSL Cert
後端的 Server 都不用動,只需要檢查原始碼將有寫 http 絕對連結的 html tag 改掉就好
這樣也可以將 https 加解密的 Loading 從 Web Server 移到 Reverse Proxy 這台來

方法很簡單,只要用 Binding Host Header 的方式掛上憑證就可以了
麻煩的是 Let's Encrypt 需要每三個月更新憑證

查了很久最後找到正確的語法並寫成 Powershell Script

$BindingURL 是憑證的主要名稱
$PublishedURLs 是陣列,填入 IIS Site 所 Binding 的多個 Host Header

*. Let's Encrypt 並沒有提供 WildCard
但可以用一張憑證包含所有 Alternative FQDN

**. 如果你的憑證存放在 Personal 容器中
就搜尋 Cert:\LocalMachine\WebHosting
改成 Cert:\LocalMachine\My

========= 程式開始 =========


$BindingURL = "www.contoso.com"
$PublishedURLs = @()
$PublishedURLs += "www.contoso.com"
$PublishedURLs += "web.contoso.com"

$LetsEncryptWinSimplePath = "C:\LetsEncryptWinSimple\"
$PFXPath = "C:\ProgramData\win-acme\httpsacme-v01.api.letsencrypt.org\"

cd $LetsEncryptWinSimplePath
$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 ""

$CommandLine = $LetsEncryptWinSimplePath
$CommandLine+="letsencrypt.exe --renew"
cmd /c $CommandLine

# -----------------

Import-Module WebAdministration

$PFXFullPath = "$PFXPath$BindingURL-all.pfx"
$NewCertProperties = Get-PfxCertificate -FilePath $PFXFullPath | Select Thumbprint,NotAfter
$LastCertProperties = Get-ChildItem -Path "Cert:\LocalMachine\WebHosting" | where {$_.Thumbprint -eq $(Get-ChildItem IIS:SSLBindings | where {$_.Host -eq $BindingURL}).Thumbprint} | select Thumbprint,NotAfter

$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) {
 write-host "New Cert's ExpireDate is Less then 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 "*** Import New Cert"
write-host ""

$CommandLine = 'C:\Windows\System32\certutil.exe -f -p "" -importpfx "WebHosting" "'+$PFXFullPath+'"'
cmd /c $CommandLine

write-host ""
write-host "*** Enable New Cert on Remote Desktop Gateway"
write-host ""

ForEach ($PublishedURL in $PublishedURLs) {

Get-ChildItem "IIS:SSLBindings\!443!$PublishedURL" | Remove-Item

Remove-WebBinding -Name "IIS WebSite Name" -Protocol "https" -Port 443 -IPAddress "*" -HostHeader $PublishedURL
New-WebBinding -Name "IIS WebSite Name" -Protocol "https" -Port 443 -IPAddress "*" -HostHeader $PublishedURL -SslFlags 1

$bind = Get-WebBinding -Name "IIS WebSite Name" | where {$_.bindingInformation -like "*$PublishedURL*"}
$bind.AddSslCertificate($NewCertThumbprint, "WebHosting")
}

write-host ""
write-host "*** Remove Last Cert"
write-host ""

if ($LastCertThumbprint -ne "") {
Get-ChildItem -Path "Cert:\LocalMachine\WebHosting" | where {$_.Thumbprint -eq $LastCertThumbprint} | Remove-Item -Confirm:$false
}

Stop-Transcript
exit;

沒有留言:

張貼留言