[After posting this blog, I have realized that Powershell 3.0 already provides a built-in cmdlet called Resolve-DnsName which could help you make any kind of DNS queries. But I still wanted to leave this blog post active for those who might want to see how it could be done with Win32 API. Also Powershell 3.0 is available only on Windows 8/Windows server 2012 and forward which means you still need another way of doing your own SRV queries for earlier OS versions]
Hi there,
While working on another tool that I mentioned in the previous blog post, I needed to lookup SRV records from powershell script. Under normal circumstances, we should be able to call any .Net API through powershell and considering that there’s a Dns class already implemented in the System.net namespace, this shouldn’t be a tough thing. But when you check the Dns class, you’ll see that it doesn’t allow you to make SRV queries:
http://msdn.microsoft.com/en-us/library/system.net.dns_methods.aspx Dns Methods
After some research I have concluded that it might be easier and faster to implement it with Win32 code. The below code just returns the host part of DNS SRV response as I only needed that part but it’s just a matter of uncommenting the printf() statements in the below code. Here is the full code that could be complied from Visual studio:
// dnssrvclient.cpp : Defines the entry point for the console application.// #include "stdio.h" #include "winsock2.h" #include "windows.h" #include "windns.h" int wmain( int argc, wchar_t *argv[ ], wchar_t *envp[ ] ) { PWSTR resultname; PDNS_RECORD ppQueryResultsSet = NULL; // ppQueryResultsSet = (PDNS_RECORD) malloc(sizeof(DNS_RECORD)); // memset(ppQueryResultsSet,'\0',sizeof(DNS_RECORD)); int retvalue; // printf("Sending SRV query for the name '%S'. Please wait...\n",argv[1]); retvalue = DnsQuery( argv[1], DNS_TYPE_SRV, DNS_QUERY_BYPASS_CACHE, NULL, &ppQueryResultsSet, NULL ); if(!retvalue) { resultname = ppQueryResultsSet->Data.SRV.pNameTarget; printf("%S",resultname); // printf("SRV query succeeded.\n"); // printf("SRV record name:\t %S \n", resultname); // printf("SRV record port:\t %d \n", ppQueryResultsSet->Data.SRV.wPort); // printf("SRV record priority:\t %d \n", ppQueryResultsSet->Data.SRV.wPriority); return retvalue; } else { // printf("The SRV record couldn't be resolved, error code: %d",retvalue); return retvalue; } }
Note: If you decide to compile the above code, please make sure that Windows Kit (SDK) is already installed on the Visual Studio client and make sure that you add the dnsapi.lib as an additonal options from linker properties.
Basically the application calls the DnsQuery() API with parameters stating that it would be an SRV query and the local DNS client cache will be bypassed when resolving the name. Once the result is returned, the application simply returns the Data.SRV.pNameTarget which holds the name part of SRV query response. You can see below an example run of the application code:
C:\> dnssrvclient.exe _sip._tls.contoso.com
sip.contoso.com
Note: _sip._tls.contoso.com is the SRV record being queried and sip.contoso.com is the result of this SRV lookup. If the query fails, the application returns a non-zero value
If you need to use the application from a powershell script, you can use a code similar below:
Note: The powershell code snipet below assumes that dnssrvclient.exe exists within the same folder.
$result = .\dnssrvclient.exe _sip._tls.contoso.com if($LASTEXITCODE) { Write-Host "DNS SRV query failed, error code: $LASTEXITCODE" -ForegroundColor Red } else { write-host "DNS SRV query succeeded: $result" -ForegroundColor Green }
A successful run will be like below:
DNS SRV query succeeded: sip.contoso.com
When SRV lookup fails, you should a response similar to below:
DNS SRV query failed, error code: 9003
Hope this helps
Thanks,
Murat
In a previous blog post of mine, I went through the steps of decrypting SSL/TLS traffic by using wireshark and openssl tools. In this blog post, I wanted to talk about the same procedure again because it got even easier to decrypt encrypted traffic with Wireshark since then.
Here are the steps to export a certificate with private key included and using that certificate to decrypt SSL/TLS session in Wireshark:
=> Exporting the certificate with its private key:
The certificate could be exported by using certificates mmc on Windows:
The exported certificate (with private key included) is c:\servercert.pfx
=> Capturing a network trace where an SSL/TLS session is established:
- To start capturing network traffic:
- Reproduce the issue
- To stop capturing network traffic:
=> Decrypting the SSL/TLS session by using Wireshark and the given certificate with private key:
- In the below example
Server IP is 10.2.2.2 and TCP port is 443.
Note: The password shown below is the one that you assigned while exporting the server certificate:
Once the certificate is applied to Wireshark, then an appropriate Wireshark filter (the filter is “http” in this example) could be applied to see the traffic in clear text:
The problem with decrypted SSL/TLS sessions is that you cannot save the network trace in an unencrypted format (best to my knowledge that’s also something Wireshark dev’s to do list) for later analysis or for sharing with someone external to your company, so if you want to save the output in clear text, you might want to print the packets to a text file. But it would also be good to expand all relevant protocol headers before doing so so that the text file will include all application layer protocol header lines expanded. You can see an example below for HTTP protocol:
We expand “Hypertext Transfer Protocol” and “Line-based text data: text/html” lines:
Now we can print the packets to a text file as given below:
with the following options set:
Now the output will be written to a text file where the HTTP request/response header+payloads will be visible in clear test:
Hi again,
In this blog post, I want to talk about a Lync 2013 problem where external users fail to upload powerpoint presentations. When external Lync user tries to upload a ppt file to an online meeting, basically nothing happens and once the failure occurs, all web conferencing related features are greyed out on the client afterwards as displayed below:
Interestingly the same issue happened with any file uploads not just ppt files and it was possible to reproduce the behavior even with Lync 2010 client. These findings eliminated an Office Webapps issue. Interestingly the client was able to establish a session with Webconf edge service as per the network trace collected on the client:
Note: The real web conferencing server IP address was deliberately replaced with 192.168.220.7 for privacy purposes.
No. Time Delta Source Destination Protocol Length Info
3892 2013-09-26 11:20:53.672 0.000 192.168.1.30 192.168.220.7 TCP 66 65021 > 443 [SYN] Seq=0 Win=8192 Len=0 MSS=1460 WS=4 SACK_PERM=1
3893 2013-09-26 11:20:53.796 0.123 192.168.220.7 192.168.1.30 TCP 66 443 > 65021 [SYN, ACK] Seq=0 Ack=1 Win=4356 Len=0 MSS=1452 WS=1 SACK_PERM=1
3894 2013-09-26 11:20:53.796 0.000 192.168.1.30 192.168.220.7 TCP 54 65021 > 443 [ACK] Seq=1 Ack=1 Win=132132 Len=0
3895 2013-09-26 11:20:53.797 0.001 192.168.1.30 192.168.220.7 TLSv1 183 Client Hello
3903 2013-09-26 11:20:53.927 0.130 192.168.220.7 192.168.1.30 TLSv1 1506 Server Hello, Certificate[Unreassembled Packet]
3904 2013-09-26 11:20:53.934 0.006 192.168.220.7 192.168.1.30 TLSv1 1506 Ignored Unknown Record
3905 2013-09-26 11:20:53.934 0.000 192.168.1.30 192.168.220.7 TCP 54 65021 > 443 [ACK] Seq=130 Ack=2905 Win=132132 Len=0
3906 2013-09-26 11:20:53.941 0.006 192.168.220.7 192.168.1.30 TLSv1 1506 Ignored Unknown Record
3907 2013-09-26 11:20:53.941 0.000 192.168.220.7 192.168.1.30 TLSv1 200 Ignored Unknown Record
3908 2013-09-26 11:20:53.941 0.000 192.168.1.30 192.168.220.7 TCP 54 65021 > 443 [ACK] Seq=130 Ack=4503 Win=132132 Len=0
3909 2013-09-26 11:20:53.950 0.008 192.168.1.30 192.168.220.7 TLSv1 368 Client Key Exchange, Change Cipher Spec, Encrypted Handshake Message
3918 2013-09-26 11:20:54.075 0.125 192.168.220.7 192.168.1.30 TCP 60 443 > 65021 [ACK] Seq=4503 Ack=444 Win=4799 Len=0
3919 2013-09-26 11:20:54.079 0.003 192.168.220.7 192.168.1.30 TLSv1 101 Change Cipher Spec, Encrypted Handshake Message
3920 2013-09-26 11:20:54.080 0.001 192.168.1.30 192.168.220.7 TLSv1 898 Application Data
3928 2013-09-26 11:20:54.215 0.134 192.168.220.7 192.168.1.30 TCP 60 443 > 65021 [ACK] Seq=4550 Ack=1288 Win=5643 Len=0
3929 2013-09-26 11:20:54.215 0.000 192.168.1.30 192.168.220.7 TLSv1 83 Application Data
3931 2013-09-26 11:20:54.335 0.119 192.168.220.7 192.168.1.30 TCP 60 443 > 65021 [ACK] Seq=4550 Ack=1317 Win=5672 Len=0
3973 2013-09-26 11:20:55.080 0.745 192.168.1.30 192.168.220.7 TLSv1 1094 Application Data
3982 2013-09-26 11:20:55.218 0.137 192.168.220.7 192.168.1.30 TCP 60 443 > 65021 [ACK] Seq=4550 Ack=2357 Win=6712 Len=0
5353 2013-09-26 11:21:23.238 28.019 192.168.1.30 192.168.220.7 TLSv1 86 Application Data
5360 2013-09-26 11:21:23.420 0.182 192.168.220.7 192.168.1.30 TCP 60 443 > 65021 [ACK] Seq=4550 Ack=2389 Win=6744 Len=0
On the other hand, there was a weird behavior that was observed in the above trace. If you pay closer attention, you’ll see that there’s no response from Web conferencing edge service at application layer even though the client gets TCP ACKs at transport layer.
Then I checked the topology file and realized that there were two Edge servers in the Edge pool and the webconf edge IP address that the Lync client was communicating with didn’t belong to any of the edge servers which means there was a HW load balancer publishing the Edge server pool. Our customer also confirmed that there was an F5 load balancer running in front of the Edge pool.
I asked our customer to bypass the HW load balancer by putting one of the Edge Server’s dedicated IP addresses for access edge/webconf edge/av edge services in the HOSTS file on the external Lync 2013 client. Once that was done the issue did’t occur anymore which means either load balancer itself has a configuration or similar problem or there’s a connectivity problem with the F5 load balancer and the Edge server external interfaces.
While working on a Lync connectivity test tool, I developed a STUN/TURN server connectivity test script in powershell which might be handy when you want to make sure that your external clients will be able to communicate with STUN/TURN server via UDP 3478 (STUN/TURN connectivity through TCP will also be added later on). Actually we have a resource kit tool called MsTurnPing which provides similar functionality (and more):
http://technet.microsoft.com/en-us/library/jj945604.aspx Lync Server 2013 Resource Kit Tools Documentation
MsTurnPing
--------------------------------------------------------------------------------
The MSTurnPing tool allows an administrator of Microsoft Lync Server 2013 communications software to check the status of the servers running the Audio/Video Edge and Audio/Video Authentication services as well as the servers that are running Bandwidth Policy Services in the topology.
Description
The MSTurnPing tool allows an administrator of Lync Server 2013 communications software to check the status of the servers running the Audio/Video Edge and Audio/Video Authentication services as well as the servers that are running Bandwidth Policy Services in the topology.
The tool allows the administrator to perform the following tests:
1. A/V Edge Server test: The tool performs tests against all A/V Edge Servers in the topology by doing the following:
◦ Verifying that the Lync Server Audio/Video Authentication service is started and can issue proper credentials.
◦ Verifying that the Lync Server Audio/Video Edge service is started and can allocate the resources on the external edge successfully.
2. Bandwidth Policy Service test: The tool performs tests against all the servers that are running the Bandwidth Policy Services in the topology by doing the following:
◦ Verifying that the Lync Server Bandwidth Policy Service (Authentication) is started and can issue proper credentials.
◦ Verifying that the Lync Server Bandwidth Policy Service (Core) is started and can perform the bandwidth check successfully.
This tool must be run from a computer that is part of the topology and has the local store installed.
Unfortunately MsTurnPing tool doesn’t allow you to do the testing from an external client.
Now let me further explain what the powershell script does to test TURN/STUN connectivity test:
1) First of all, to do the testing you need to provide your AV edge server’s name/IP address information as a parameter to the powershell script:
Example:
PS C:\> turn.ps1 av.contoso.com
2) Once the powershell script runs, it does:
- Resolve the name
- If the given name is successfully resolved, it then sends a UDP datagram with a STUN allocate payload
- It waits on a response on the UDP socket for a timeout period and if there’s a STUN allocate response it prints “Received response from STUN Server!”
- If no response is received within the given timeout period, it prints an error.
Some example outputs:
If you get such a failure, one of the first things that you can do is to run the below commands on your Edge server(s) and see if listens on UDP port 3478 on the internal IP and on the AV Edge IP:
C:\Users\Administrator.CONTOSO>netstat -ano | find ":3478"
UDP 10.2.2.10:3478 *:* 1952
UDP 10.3.3.12:3478 *:* 1952
C:\Users\Administrator.CONTOSO>tasklist /svc | find "1952"
MediaRelaySvc.exe 1952 RTCMEDIARELAY
If you don’t know what is your AV Edge server name/IP address, you can check it from the topology file:
=> Here is the full Powershell script source:
#------------SCRIPT STARTS HERE-----------
function ResolveLyncNames {
param($LyncFqdn)
try {
$ipaddr = [System.Net.Dns]::GetHostAddresses($LyncFqdn)
Write-Host "Successfully resolved $LyncFqdn to $ipaddr" -ForegroundColor Green
return $ipaddr
}
catch {
$exception = New-Object system.net.sockets.socketexception
$errorcode = $exception.ErrorCode
write-host "Requested name '$LyncFqdn' could not be resolved, error code:$errorcode" -foregroundcolor Red
write-host "Error details: $exception" -foregroundcolor Red
return 0
if($args[0] -eq $NULL)
{
Write-host "Please specify a STUN server name or IP address to test"
Write-Host "Example: turn.ps1 av.contoso.com"
return
$stunserver1 = $args[0]
if(ResolveLyncNames($stunserver1)) {
$j = Start-Job -ScriptBlock {
$stunserver2 = $args[0]
$udpclient=new-Object System.Net.Sockets.UdpClient
$udpclient.Connect($stunserver2,3478)
[Byte[]] $payload =
0x00,0x03,0x00,0x64,0x21,0x12,0xa4,0x42,0xf1,0x3c,0x08,0x4b,
0x80,0x18,0x17,0x72,0x47,0x49,0x30,0x65,0x00,0x0f,0x00,0x04,
0x72,0xc6,0x4b,0xc6,0x80,0x08,0x00,0x04,0x00,0x00,0x00,0x04,
0x00,0x06,0x00,0x38,0x02,0x00,0x00,0x24,0x79,0xb7,0x95,0x2d,
0x01,0xce,0xa8,0x6e,0x4e,0x3d,0x76,0x22,0x64,0xaa,0xc7,0xb6,
0x2b,0xb8,0x78,0xde,0xee,0x8a,0xc0,0x88,0x84,0x49,0x1b,0x7c,
0x00,0x00,0x00,0x00,0x82,0x8b,0x73,0x75,0xdd,0x0c,0xae,0x66,
0x95,0xed,0xef,0x56,0xd0,0x4b,0x54,0xa4,0x7c,0xbd,0xfa,0x98,
0x00,0x10,0x00,0x04,0x00,0x00,0x00,0xc8,0x80,0x06,0x00,0x04,
0x00,0x00,0x00,0x01,0x80,0x55,0x00,0x04,0x00,0x01,0x00,0x00
$bytesSent=$udpclient.Send($payload,$payload.length)
$listenport = $udpclient.client.localendpoint.port
$endpoint = new-object System.Net.IPEndPoint ([IPAddress]::Any,$listenport)
$content = $udpclient.Receive([ref]$endpoint)
$Encoding = "ASCII"
switch ( $Encoding.ToUpper() )
"ASCII" { $EncodingType = "System.Text.ASCIIEncoding" }
"UNICODE" { $EncodingType = "System.Text.UnicodeEncoding" }
"UTF7" { $EncodingType = "System.Text.UTF7Encoding" }
"UTF8" { $EncodingType = "System.Text.UTF8Encoding" }
"UTF32" { $EncodingType = "System.Text.UTF32Encoding" }
Default { $EncodingType = "System.Text.ASCIIEncoding" }
$Encode = new-object $EncodingType
if ($Encode.GetString($content).Contains("The request did not contain a Message-Integrity attribute")) {
write-host "Received response from STUN Server!" -ForegroundColor Green
else {
write-host "STUN Server either is not reachable or doesn't respond" -ForegroundColor Red
$udpclient.Close()
} -ArgumentList $stunserver1
write-host "Sending TURN server port allocation request at UDP port 3478, it will be checked after 10 seconds to see if a response is received or not ..." -ForegroundColor Green
Start-Sleep -Seconds 10
if( $j.JobStateInfo.State -ne "completed" )
Write-Host "The request timed out, STUN Server '$stunserver1' is not reachable or doesn't respond to the request." -ForegroundColor Red
Write-host "Please check if UDP 3478 is allowed between the client and the STUN server" -ForegroundColor Red
Write-Host "Also please check if STUN server (MediaRelaySvc.exe) is running on the Edge server and listening on UDP 3478" -ForegroundColor Red
$results = Receive-Job -Job $j
$results
$_.exception.message
#------------SCRIPT ENDS HERE-----------