Hi there,
In this blog post, I’ll be talking about another powershell based tool which could be used to check name resolution, TCP layer connectivity and SSL/TLS negotiation for various URLs that are accessible through your reverse proxy which are:
- External web services URL
- Meet URL
- Office WebApps URL
- Lyncdiscover URL
- Dialin URL
When the tool is run, you can see if the given URL is successfully resolved to a name. If name resolution succeeds, a TCP session is attempted to the target and if the TCP session successfully created an SSL/TLS negotiation is done with the target URL. And if that succeeds as well, the subject names and subject alternative names in the returned certificate are dumped by the tool. Also expiration time of each certificate is dumped.
You’ll have to provide each URL manually (actually I was planning to read all such details from topology file removing the requirement of manual input but due to some issues I decided to enter the information manual for the time being).
Such URL details could be easily obtained from your topology file:
- External Web services FQDN:
- Meet URL and Dialin URL:
- Office WebApps URL:
- Lyncdiscover URL:
Lyncdiscover URL is built by adding “lyncdiscover” to the beginning of sip domain. Examples:
lyncdiscover.contoso.com
lyncdiscover.fabrikam.com
=> Here is the full Powershell script source:
#------------SCRIPT STARTS HERE-----------
# ResolveLyncNames() resolves various Lync names to IP addresses
function ResolveLyncNames {
param($LyncFqdn)
try {
$ipaddr = [System.Net.Dns]::GetHostAddresses($LyncFqdn)
Write-Host "Successfully resolved $LyncFqdn to $ipaddr" -ForegroundColor Green
return 1
}
catch {
$exception = New-Object system.net.sockets.socketexception
$errorcode = $exception.ErrorCode
write-host "Name resolution failed, error code:$errorcode" -foregroundcolor Red
write-host "Error details: $exception" -foregroundcolor Red
return 0
# TLSConnectionCheck() establishes TLS session to remote host at the given TCP port
function TLSConnectionCheck {
param ($remotehost,$remoteport)
$TCPConnection = New-Object System.Net.Sockets.Tcpclient($remotehost, $remoteport)
Write-Host "TCP connection has succeeded" -ForegroundColor Green
$TCPStream = $TCPConnection.GetStream()
$SSLStream = New-Object System.Net.Security.SslStream($TCPStream)
Write-Host "SSL connection has succeeded" -ForegroundColor Green
$SSLStream.AuthenticateAsClient($remotehost)
Write-Host "SSL authentication has succeeded" -ForegroundColor Green
Write-Host "There's a problem with SSL authentication to $remotehost" -ForegroundColor Red
return
$certificate = $SSLStream.get_remotecertificate()
$certificateX509 = New-Object system.security.cryptography.x509certificates.x509certificate2($certificate)
$SANextensions = New-Object system.security.cryptography.x509certificates.x509Certificate2Collection($certificateX509)
$SANextensions = $SANextensions.Extensions | Where-Object {$_.Oid.FriendlyName -eq "subject alternative name"}
Write-Host "=> Remote host certificate details:"
Write-Host "Issuer: " $SSLStream.RemoteCertificate.Issuer -ForegroundColor Green
Write-Host "Subject name: " $SSLStream.RemoteCertificate.Subject -ForegroundColor Green
Write-Host "Expiration time: " $SSLStream.RemoteCertificate.GetExpirationDateString() -ForegroundColor Green
Write-Host "Serial number: " $SSLStream.RemoteCertificate.GetSerialNumberString() -ForegroundColor Green
Write-Host "=> Subject alternative names: "
$SANextensions.Format(1)
Write-Host "Please make sure that Subject name and Subject alternative names in the certificate are compatible with the names given in http://technet.microsoft.com/en-us/library/gg429704.aspx" -BackgroundColor DarkCyan
Write-Host "Wildcard names in SAN are supported for meet, dialin and Lyncdiscover URLs. Please see http://technet.microsoft.com/en-us/library/hh202161.aspx for more details" -BackgroundColor DarkCyan
Write-Host "$remotehost doesn't support SSL connections at TCP port $remoteport" -foregroundcolor Red
write-host "TCP connection to $remotehost failed, error code:$errorcode" -foregroundcolor Red
#
# TESTING
write-host "Please enter your external Web services FQDN. This could be seen from your Lync topology. You can skip it by pressing Enter. Example: webext.contoso.com" -ForegroundColor Green
$LyncExternalWebserviceFqdn = Read-Host
write-host "Please enter your meet URL. This could be seen from your Lync topology. You can skip it by pressing Enter. Example: meet.contoso.com" -ForegroundColor Green
$SimpleURL_meet = Read-Host
write-host "Please enter your Office WebApp server FQDN. This could be seen from your Lync topology. You can skip it by pressing Enter. Example: wac.contoso.com" -ForegroundColor Green
$LyncWac = Read-Host
write-host "Please enter your Lyncdiscover URL. You can skip it by pressing Enter. Example: lyncdiscover.contoso.com" -ForegroundColor Green
$SimpleURl_lyncdiscover = Read-Host
write-host "Please enter your dialin URL. This could be seen from your Lync topology. You can skip it by pressing Enter. Example: dialin.contoso.com" -ForegroundColor Green
$SimpleURL_dialin = Read-Host
# ==============================================================================================
# Resolve and access external web service fqdn
Write-Host "================================================================================================================"
Write-Host "TEST 1: External Web service FQDN name resolution and access tests" -ForegroundColor yellow
$LyncExternalWebserviceFqdnport = 443
If([string]::IsNullOrEmpty($LyncExternalWebserviceFqdn)) {
Write-Host "External Web services URL is NULL. Bypassing External web services accessibility check"
else {
Write-Host "=> Attempting to resolve External Web Service fqdn ("$LyncExternalWebserviceFqdn" )"
if(ResolveLyncNames($LyncExternalWebserviceFqdn)) {
Write-Host "=> Attempting to connect to External Web Service fqdn ("$LyncExternalWebserviceFqdn" ) at TCP port $LyncExternalWebserviceFqdnport"
TLSConnectionCheck $LyncExternalWebserviceFqdn $LyncExternalWebserviceFqdnport
# Resolve and access Meet URL
Write-Host "TEST 2: Meet URL name resolution and access tests" -ForegroundColor yellow
If([string]::IsNullOrEmpty($SimpleURL_meet)) {
Write-Host "Meet URL is NULL. Bypassing Meet URL accessibility check"
$SimpleURL_meet_port = 443
Write-Host "=> Attempting to resolve Meet URL ("$SimpleURL_meet" )"
if(ResolveLyncNames($SimpleURL_meet)) {
Write-Host "=> Attempting to connect to Meet URL ("$SimpleURL_meet" ) at TCP port $SimpleURL_meet_port"
TLSConnectionCheck $SimpleURL_meet $SimpleURL_meet_port
# Resolve and access Office WebApps URL
Write-Host "TEST 3: Office WebApps server FQDN name resolution and access tests" -ForegroundColor yellow
$LyncWacport = 443
If([string]::IsNullOrEmpty($LyncWac)) {
Write-Host "Office WebApps URL is NULL. Bypassing Office WebApps services accessibility check"
Write-Host "=> Attempting to resolve Office WebApps server fqdn ("$LyncWac" )"
if(ResolveLyncNames($LyncWac)) {
Write-Host "=> Attempting to connect to resolve Office WebApps server fqdn ("$LyncWac" ) at TCP port $LyncWacport"
TLSConnectionCheck $LyncWac $LyncWacport
# Resolve and access Lyncdiscover URL
Write-Host "TEST 4: Lyncdiscover URL name resolution and access tests" -ForegroundColor yellow
If([string]::IsNullOrEmpty($SimpleURl_lyncdiscover)) {
Write-Host "Lyncdiscover URL is NULL. Bypassing Lyncdiscover URL accessibility check"
$SimpleURL_lyncdiscover_port = 443
Write-Host "=> Attempting to resolve Admin URL ("$SimpleURl_lyncdiscover" )"
if(ResolveLyncNames($SimpleURl_lyncdiscover)) {
Write-Host "=> Attempting to connect to Admin URL ("$SimpleURl_lyncdiscover" ) at TCP port $SimpleURL_lyncdiscover_port"
TLSConnectionCheck $SimpleURl_lyncdiscover $SimpleURL_lyncdiscover_port
# Resolve and access Dialin URL
Write-Host "TEST 5: Dialin URL name resolution and access tests" -ForegroundColor yellow
If([string]::IsNullOrEmpty($SimpleURL_dialin)) {
Write-Host "Dialin URL is NULL. Bypassing Dialin URL accessibility check"
$SimpleURL_dialin_port = 443
Write-Host "=> Attempting to resolve Dialin URL ("$SimpleURL_dialin" )"
if(ResolveLyncNames($SimpleURL_dialin)) {
Write-Host "=> Attempting to connect to Dialin URL ("$SimpleURL_dialin" ) at TCP port $SimpleURL_dialin_port"
TLSConnectionCheck $SimpleURL_dialin $SimpleURL_dialin_port
#------------SCRIPT ENDS HERE-----------
=> You can also find a sample output below:
Hope this helps
Thanks,
Murat
In this blog post, I’ll be talking about a powershell based tool which could be used to check Exchange EWS connectivity especially from external Lync clients where the client might not be able to access Exchange EWS and hence cannot display meetings and similar.
The powershell tool uses Exchange EWS managed API to connect to EWS service, so you have to install the API to the test client from where you plan to run the script. The library could be downloaded at:
http://www.microsoft.com/en-us/download/details.aspx?id=35371 Microsoft Exchange Web Services Managed API 2.0
function TestExternalEWS () {
param($emailaddress)
Add-Type -Path 'C:\Program Files\Microsoft\Exchange\Web Services\2.0\Microsoft.Exchange.WebServices.dll'
write-host "=> Retrieving your credentials for EWS connectivity (Domain\User and password) ..." -ForegroundColor Green
$autod = New-Object Microsoft.Exchange.WebServices.Autodiscover.AutodiscoverService
$Credentials = (Get-Credential)
$creds=New-Object System.Net.NetworkCredential($Credentials.UserName.ToString(),$Credentials.GetNetworkCredential().password.ToString())
$autod.Credentials=$creds
$autod.EnableScpLookup = $false
$autod.RedirectionUrlValidationCallback = {$true}
$autod.TraceEnabled = $TraceEnabled
write-host "=> Retrieving external EWS URL via Autodiscover service for the given smtp address '$emailaddress' ..." -ForegroundColor Green
Write-Host
$response = $autod.GetUserSettings(
$emailaddress,
[Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::ExternalMailboxServer,
[Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::ExternalEcpUrl,
[Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::ExternalEwsUrl,
[Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::ExternalOABUrl,
[Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::ExternalUMUrl,
[Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::ExternalWebClientUrls
)
$ExternalEwsUrl = $response.Settings[[Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::ExternalEwsUrl]
if($ExternalEwsUrl -eq $NULL) {
write-host "=> Successfully contacted Exchange Autodiscover service but couldn't retrieve autodiscovery settings for the given smtp address '$emailaddress'" -ForegroundColor Red
write-host "Error code:" $response.errormessage
write-host "=> Successfully contacted Autodiscover service and retrieved the external EWS URL for the given smtp address '$emailaddress'" -ForegroundColor green
write-host $externalEwsUrl -ForegroundColor Magenta
write-host
write-host "There was an error calling GetUserSettings() function, the error returned:" $_.exception.message -ForegroundColor Red
# Got the EWS URL information, now testing EWS access
write-host "=> Now making a test call (retrieving given user's OOF settings) to Exchange Web Service to test external EWS connectivity against '$externalEwsUrl' ..." -ForegroundColor Green
$service = new-object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2007_SP1)
$uri=[system.URI] $ExternalEwsUrl
$service.Url = $uri
$oofsettings = $service.GetUserOofSettings($emailaddress)
Write-host "=> Successfully retrieved OOF settings." -foreground Green
write-host "OOF state: " $oofsettings.State
write-host "External OOF reply:"
write-host "============================================================================================================================================="
write-host $oofsettings.externalreply
write-host "There was an error calling GetUserOofSettings() function, the error returned:" $_.exception.message -ForegroundColor Red
if(($args[0] -eq $NULL))
{
Write-host "Please specify e-mail address to test"
Write-Host "Example: testlyncext.ps1 user-email@contoso.com"
$emailaddress = $args[0]
TestExternalEWS($emailaddress)
You can find a sample output below: