Setup a Fully Functional Lync 2013 Lab Using only One Public IP Address

Note: This article assumes you know how to setup Lync 2013 already and just need to know the intricacies of changing the default ports.

Ever since I was exposed to Lync in 2011, I’ve been a huge proponent of using chat to communicate at work. Years ago, I recall corporate chat being a hard sell, but now it seems generally accepted; many customers who don’t use chat are open to it, they just haven’t have the resources to set it up yet. I’ve setup Google Apps w/Talk for small businesses in the past, but I’ve have been curious implementing Microsoft Lync on-premise so I setup a lab last week to better understand it.

Because my lab is limited on RAM, I attempted to use just one server to accomplish everything I wanted — chat, “PC-to-PC” calls, and video conferencing. I was able to get chat working fine for internal and external users, but video conferencing and calls failed for users who were not on the same internal network.

After learning about the Edge server’s role in providing media services, I gave in and added an Edge server to my topology. I also added a Reverse Proxy because holy smokes, setting up a Reverse Proxy using IIS ARR was way easier than I thought it’d be (and I already had a web server that could do this.)

Here’s the thing about the Edge server: both the Front End and the Edge server use port 443 for very different things. Autodiscovery, which is provided by the Front End/Reverse Proxy, requires HTTPS (though you can use HTTP but I don’t want), and Autodiscovery was a requirement that I gave myself so, I was left having to modify the A/V port for the Edge server. In the setup below, you can see that I changed it to port 442. Modifying the port in the Topology was easy enough, but then I had to figure out exactly what DNS records needed to change.

The DNS change seems obvious now, but I started this with little knowledge about AutoDiscovery and service records. Because of this, I ended up with a ton of unnecessary/incorrect DNS entries.

Here’s how my lab is configured:

Network
Internal SIP domain: ad.local
External SIP domain: acme.com
External IP address 24.0.175.22
DMZ Subnet: 10.0.10.x
Internal Subnet: 10.0.0.x

Servers
Role Hostname Internal IP External IP
Lync Front End lyncfe.ad.local 10.0.0.20 None
Lync Edge lyncedge 10.0.10.5 10.0.0.5
Reverse proxy (optional) rp 10.0.10.2 10.0.0.2

Port Forwarding
Protocol Port Function IP
TCP 443 Autodiscovery (HTTPS) 10.0.10.2
TCP 442 STUN/SIP/PSOM 10.0.10.5
TCP 444* Web Conferencing 10.0.10.5
UDP 3478 STUN 10.0.10.5
TCP 5061** MTLS 10.0.10.5
Both 50000-59999 RTP 10.0.10.5

* I’m not entirely sure this needs to be exposed, but I opened mine anyway.
** In order to support the widest variety of Lync clients, 5061 appears to
be required for authentication even if you don’t do federation.


External DNS A & CNAME Records
Type Hostname Points to
A lync.acme.com 24.0.175.222
CNAME sip.acme.com lync.acme.com
CNAME meet.acme.com lync.acme.com
CNAME lyncdiscover.acme.com lync.acme.com

External DNS SRV Record
Service Protocol Port Target
_sip _tls 442 lync.acme.com



Some DNS providers offer an SRV Host field. This is useful if your users authenticate as [email protected] instead of [email protected] In this case, “x” would be your host. Also, I’ve seen different numbers of Priority and Weight. I left mine at 100 and 1, though I’ve seen it at 0 and 0. I don’t think it matters much unless you’re doing load balancing.

Also, after examining client logs, I noticed that some external logins for desktop clients failed when sip.acme.com didn’t exist, so I added it to DNS. Microsoft documentation mentions A records in a whole lot of places, but I found CNAMES work just as well.

A few things to note:

I didn’t hook Lync into Exchange and I didn’t even attempt Enterprise Voice because I don’t have the equipment (or desire.) Authentication was accomplished by adding [email protected] to each AD account email property, then using [email protected] as the sign-in name and ad\username for User Name. Of course, my domain’s Root CA cert had to be installed on all of the client computers, including mobile devices.

I did test to see if Office Web Apps was required for Lync-to-Lync calls (it wasn’t) and blew up one of my server’s IIS configs in the process. OWA doesn’t like to share and deletes all of your IIS Sites during configuration, so don’t install it on a server that does anything else related to IIS.

Also, if you have just one internal subnet and you’re comfortable with the security repercussions, you don’t need a reverse proxy — just a router that can forward from port 443 to port 4443. Also, your edge server will need 2 IPs (no way around that), so you can just give it two on the same subnet and make sure your router NATs to the “External” IP of the Edge server as listed in the Lync Topology.

Posted in Lync

Running Lync 2010 with a SQL Server 2012 Backend

Recently I was tasked with migrating all SQL 2008 R1 and prior databases to SQL 2008 R2 and SQL 2012.  One of my qualifying applications was Lync 2010.  We were under the impression that SQL 2012 would be fine for the Lync 2010 installation.  After migrating the database and updating the connections, Lync would not fully initialize.

After running a quick trace, I discovered that some of the Lync processes were calling sp_dboption.  SQL Server 2012 does not have this stored procedure any longer.  So to remedy the situation, I scripted sp_dboption from the system procedures on SQL 2008 R1 and manually created it on SQL 2012 as a user stored procedure.  After granting execute permissions to the user, Lync 2012 started right up.

We’ve been running on SQL Server 2012 for months without further issue.

Posted in Lync, SQL Server

PowerShell v3: Get Volume Information for Clustered SQL Server Storage

Unfortunately, there are no native PowerShell Failover Cluster cmdlets which will give you the volume information for disks in a cluster. I’ve seen some bloggers use Get-ClusterSharedVolume but a Cluster Shared Volume or CSV is different from volumes used within a SQL cluster.

The script below, which was written with the help of this post on StackOverflow, gets the volume information for disks within specific SQL Server instances on all the clusters in a domain. This does not work with Availability Groups since they don’t use shared storage.

I am writing this code for another project which stores the values in a database, which is why I’m using variables and Write-Host in the example. The output will look like this (well, hopefully yours will have a more advanced storage structure. These particular clustered instances were created for proof-of-concept):

PS C:\Users\administrator> .\Get-ClusteredDiskInfo.ps1
Cluster: CLUSTER2
SQL Resource: SQL Server
Cluster disk: Cluster Disk 1
Disk state: Online
Disk Drive: Y:
Disk Label: iscsivol
Disk Size: 102269
Disk Free: 102111

Cluster: CLUSTER2
SQL Resource: SQL Server (SQL2)
Cluster disk: Cluster Disk 3
Disk state: Online
Disk Drive: F:
Disk Label: iscsivol2
Disk Size: 20476
Disk Free: 20358

Posted in PowerShell, SQL Server

PowerShell & SharePoint: Using New-WebServiceProxy to Post New Completed Tasks Automatically

Recently, I was asked to help automate a friend’s super boring daily duty of logging repetitive activities to a SharePoint Task list. Even though I’m no longer regularly working with SharePoint (yay!), I accepted the challenge.

Below is the script I created, which can be scheduled (and mixed up, even using $a = Get-Random -minimum 15 -maximum 1250; Start-Sleep -s $a within the function) to fill in the form and post new completed Tasks automatically.

Here are a few interesting things while creating this script:

  • Invoke-WebRequest is not the appropriate cmdlet for this task. SharePoint’s form field naming scheme was complex and ultimately, Invoke-WebRequest was unable to successfully submit the task. It seemed like it worked, but the new items never appeared.
  • New-WebServiceProxy works with 2007, 2010 and SharePoint 2013 (as well as PowerShell 2.0 and 3.0) but beware xml’s case sensitivity.
  • Lists.UpdateListItems is used to add new tasks, not just update tasks
  • Fields with spaces or renamed columns could present issues. Makes sure you use the FieldInternalName for the column name. This can be found in the source code of the New page.
  • A people/group picker field only requires the user id of the user in SharePoint. You can get this ID by deciphering the user’s URL or just use ResolvePrincipals as seen in this script. The format should look like this: <Field Name=’AssignedTo’>32</Field>
  • Dates require this format: YYYY-MM-DD
  • The default Description field is actually called the Body field and must be referenced as such.
  • Lookup fields work, but the code below doesn’t automatically resolve the lookup fields. I just went get the ID (by looking at the URL of the item) and manually input it.

Special thanks goes out to the PowerShell team for the jump start.

Posted in PowerShell, SharePoint

Use PowerShell v3 to Keep a CookieJar and POST to a Web Form That Prohibits XSS

In my previous post, I outlined how to use PowerShell v2 to keep a CookieJar and POST to a Web Form that Prohibits XSS. The code was 35 lines long. Upon seeing my post, Lee Holmes suggested using PowerShell v3′s Invoke-WebRequest instead to get my code down to 1/5th of its original size.

I’m astounded at how easy Invoke-WebRequest made this task. It took care of knowing what type of authentication is required (Basic, in my example), and the cookie jar/session. So now I’m down from 35 lines of code to this:

Bravo, PowerShell team :D

Posted in PowerShell

Use PowerShell to Keep a CookieJar and POST to a Web Form That Prohibits XSS

I recently had a project that required I log into a site and submit a form. Initially, I had a Start-Process that launched iexplore but then I decided it would be best to..

My initial attempts to automate this process failed with the server response “403 Forbidden.” As it turns out, the web server which is some modified version of jetty (I believe) was hardened to prevent XSS attacks. I knew that I had to use cookies, but doing so in PowerShell turned out to be a bit more challenging than it was in VBScript.

I like this script because it covers a lot of ground, from bypassing the SSL warning, to getting credentials to submitting a form. It took about a day to figure out, but ultimately, I was able to:

  1. Authenticate using BASIC authentication
  2. Bypass SSL warnings
  3. Keep cookies
  4. Submit the information from a hidden field in the form

There are additional steps in between each of those, which include

  • Prompting for the website credentials
  • Associating those credentials to the website
  • Placing cookies in the cookie jar
  • Parsing the form for the information I needed
  • Passing back the information

Essentially, I create a web request using System.Net.HTTPWebRequest (using webclient proved too messy), create a response stream, “upload” the data as bytes, get the second response. You can modify this to submit other portions of a form, or just parse from page to page. Hope you find it useful!

Thanks to Captain Abstraction for breaking this whole down and making it way easier to understand than most of the webpages I visited.

Posted in PowerShell

Summary Post: Update VMware vSphere SSL Certs

After speaking with a colleague today, I expect this list will grow as I work more with the vSphere suite. But until then, here is a consolidated list of posts and scripts that I’ve written to ease the replacement of SSL certificates on Windows-based vSphere related products using PowerShell and a Windows Domain Certificate Authority.

All SSL Certificate Replacement Posts and Scripts in this Series

vSphere 4.1-5.0 SSL Generation and Replacement Post Script
vSphere 5.1 SSL Generation and Replacement Post Script
ESX Certificate Generation and Upload Post Script
NetApp Virtual Storage Console SSL Generation and Replacement Post Script
Site Recovery Manager SSL Generation and Replacement Post Script
VMware View Composer SSL Generation and Replacement Post Script
VMware Horizon View SSL Generation and Replacement Post Script
Posted in PowerShell, Security, VMware

Update VMware Horizon View SSL Certs with your own Windows Domain CA Certificates using PowerShell

Well, this script was different. Unlike the other posts in this series, I was required to use only Microsoft command line tools instead of OpenSSL. Not that I’m opposed to using certreq and certutil — I actually started this whole cert automation project to see if it was possible to use only these tools and PowerShell, but ultimately it appeared that for whatever crypto reason, OpenSSL was required for the replacement of vSphere SSL certs.

So it was especially surprising to me that no matter how I imported/exported the OpenSSL generated keys, nothing worked until I used certreq and certutil. If anyone knows the reasons, I’d love to hear them.

ReplaceSSL-View.ps1 backs up the old certificate found in your Machine Certificate Store, adds a new one with the proper FriendlyName “vdm” and restarts all View services.

Download ReplaceSSL-View.ps1

All SSL Certificate Replacement Posts and Scripts in this Series

vSphere 4.1-5.0 SSL Generation and Replacement Post Script
vSphere 5.1 SSL Generation and Replacement Post Script
ESX Certificate Generation and Upload Post Script
NetApp Virtual Storage Console SSL Generation and Replacement Post Script
Site Recovery Manager SSL Generation and Replacement Post Script
VMware View Composer SSL Generation and Replacement Post Script
VMware Horizon View SSL Generation and Replacement Post Script
Posted in PowerShell, Security, VMware

Update VMware Site Recovery Manager SSL Certs with your own Windows Domain CA Certificates using PowerShell

Next in the series of replacing vSphere related SSL scripts is the VMware Site Recovery manager script.

This script generates the SSL certificates based off of the WebServer Certificate Template and runs a batch file to perform the actual replacement.

Once you run the script, the batch file requires two inputs from you: the password for the specified vCenter Server admin variable and the PFX certificate password, “vmwaresrm”

To reduce the likelihood of errors, the script also places the certificate password into your clipboard, so you can just right-click, paste and hit enter.

Download ReplaceSSL-SiteRecoveryManager.ps1

All SSL Certificate Replacement Posts and Scripts in this Series

vSphere 4.1-5.0 SSL Generation and Replacement Post Script
vSphere 5.1 SSL Generation and Replacement Post Script
ESX Certificate Generation and Upload Post Script
NetApp Virtual Storage Console SSL Generation and Replacement Post Script
Site Recovery Manager SSL Generation and Replacement Post Script
VMware View Composer SSL Generation and Replacement Post Script
VMware Horizon View SSL Generation and Replacement Post Script
Posted in PowerShell, Security, VMware

Update VMware View Composer SSL Certs with your own Windows Domain CA Certificates using PowerShell

Next in the series of replacing vSphere related SSL scripts is the VMware View Composer script. This one is rather simple, and uses certutil and certreq to generate the certificates, as opposed to OpenSSL.

It also generates a batch script which calls SviConfig.exe. You just gotta put in a few variables, run the script and choose the new cert (I couldn’t automate that part).

Download ReplaceSSL-Composer.ps1

Thanks to Tomas Fojta for the easy-to-understand tutorial.

All SSL Certificate Replacement Posts and Scripts in this Series

vSphere 4.1-5.0 SSL Generation and Replacement Post Script
vSphere 5.1 SSL Generation and Replacement Post Script
ESX Certificate Generation and Upload Post Script
NetApp Virtual Storage Console SSL Generation and Replacement Post Script
Site Recovery Manager SSL Generation and Replacement Post Script
VMware View Composer SSL Generation and Replacement Post Script
VMware Horizon View SSL Generation and Replacement Post Script
Posted in PowerShell, Security, VMware