Blog

Do You Use Google Reader?

Are you a Google Reader user? The backend reporting for my website tells me that a large percentage of my readers are using Google Reader, and today, June 30th is Google Reader’s last day. Please don’t forget to migrate your subscription to my blog over to your new RSS reader. With my book update out of the way, I’m working on new content to start posting again!

If you’re still evaluating options for RSS readers, I have been successfully using NextGen Reader for quite some time now. They’ve got a nice Windows Phone app as well as a great Metro app. If you login with your Google Reader account, they’ll migrate you in a couple of clicks to another service called Feedly.

Posted Sunday, June 30 2013 by Brian Desmond | Comments
Filed under:


Signing Active Directory, 5th Edition Books at TechEd North America

I’ll be at TechEd North America in New Orleans this week. On Monday, June 3rd from 6:00 to 6:30 PM, I’ll be at the O’Reilly/Microsoft Press booth, booth #511 signing copies of my new book – Active Directory, 5th Edition. If you can’t stop by then, I’ll be at the Access and Information Protection in the Microsoft Solutions Experience Monday from 12PM to 2PM and Tuesday from 12PM to 2:30PM. I’ll also be at the Ask The Experts evening event on Tuesday evening.

Posted Sunday, June 02 2013 by Brian Desmond | Comments
Filed under: Tagged as: , ,


Active Directory, 5th Edition

I’ve been remiss in posting anything here the past six months as my weekends have been consumed with an update to my book, Active Directory, 4th Edition. The writing and technical reviews  of the fifth edition are complete, thanks to Joe Richards, Mark Parris, and Mark Morowczynski. We’ve now moved in to the production cycle and a copy editor is busy fixing up my writing to make the book a polished all-around easy-to-read product. Meanwhile,  the illustrators will soon be busy with the artwork – figures, diagrams, etc. The final book is now available!

So, to summarize, Active Directory, 5th Edition is now available:

Posted Sunday, January 20 2013 by Brian Desmond | Comments
Filed under: Tagged as: , , , ,


Cisco ACE Sample Configuration for Exchange 2010

Cisco’s ACE appliances and modules are something that I see constantly at customers. Unfortunately, Cisco’s application specific documentation is rather lacking. There’s a rather simplistic sample config at http://www.cisco.com/en/US/docs/solutions/Enterprise/Data_Center/App_Networking/Exchange_VSphere_UCS_NetApp.html#wp345264, but, that doesn’t really have everything you need. The folks at F5 on the other hand have extremely well documented application guides for their hardware and that’s one of the reasons I usually send customers to F5 first. The contents of this post are essentially the same for ACE appliances and ACE modules.

In any case, the rest of this post is a working sample configuration for the topology below. A thread on a discussion alias prompted me to clean this up and post it.

image

In our sample configuration, we’ll configure the load balancer in a one-armed configuration with Source NAT (SNAT). Clients will access services via the mail.contoso.com and autodiscover.contoso.com URLs.  In addition, clients who go to a non SSL URL or go to the root instead of /owa will be redirected.

Before we get started, a few pre-requisites:

  • You should have a working context on your ACE appliance/module with resources allocated.
  • Your CAS servers should have static ports configured as described here.
  • Your SSL certificate and the necessary intermediate and root certificates should be installed on the load balancer.
  • A VIP will need to be allocated. We’ll use 192.168.100.200 in this sample
  • If you’re expecting more than ~65K client connections, you’ll need to use more than one IP in the SNAT pool. This example assumes one is enough. We’ll use 192.168.100.199 in this sample.

The entire config is posted below, but, first, I wanted to speak to a few specific elements and why they’re here:

crypto chaingroup DigiCert
  cert DigiCertRootCA
  cert DigiCertIntermediateCA
  cert mail_contoso_com
This creates a valid SSL certificate chain
serverfarm host Exchange-CAS-RPC
  predictor leastconns
  probe TCP135
  probe TCP60000
  probe TCP60001
  fail-on-all
  rserver CAS01
    inservice
  rserver CAS02
    inservice
Here we’re validating the availability of the RPC ports on the CAS server. The “fail-on-all” keyword is key here. This makes sure that if any of the three services are unavailable, the server is removed from the farm
parameter-map type http Exchange-OWA
  case-insensitive
  persistence-rebalance
  set header-maxparse-length 16384
  set content-maxparse-length 8192

There are three things going on here:

  • We’re making URL matching case insensitive
  • persistence-rebalance makes sure that each HTTP request is evaluated individually, and that sticky cookies are inserted only on the first request
  • The max parse lengths define how far into a request the ACE looks for cookies, headers, and so forth. Without this, you’ll likely see issues with partially loaded images and random session timeouts. It’s possible that you’ll need to extend the numbers here.
sticky ip-netmask 255.255.255.255 address source Exchange-CAS-RPC
  timeout 7200
  replicate sticky
  serverfarm Exchange-CAS-RPC
Here we define source IP stickiness. This is used for the RPC services.
Warning: If you have source NAT upstream (such as in a network merger scenario) where many clients are appearing to come from the same IP, this will cause load balancing to not be even.
sticky http-cookie Exchange-Sticky Exchange-CAS-HTTPS-Cookie
  cookie insert browser-expire
  replicate sticky
  serverfarm Exchange-CAS-HTTPS
Here we create a cookie valid for the life of the browser session to ensure that OWA and ECP sessions go to the same CAS server.
action-list type modify http Exchange-CAS-HTTP
  header insert request X-Forwarded-For header-value "%is"
This enables us to insert the client’s original IP as an additional HTTP header so that IIS logs can be correlated to a specific client.
policy-map type loadbalance first-match Exchange-CAS-HTTPS
  match OWA http url /owa.*
    sticky-serverfarm Exchange-CAS-HTTPS-Cookie
    action Exchange-CAS-HTTP
    ssl-proxy client Exchange-CAS
  match ECP http url /ecp.*
    sticky-serverfarm Exchange-CAS-HTTPS-Cookie
    action Exchange-CAS-HTTP
    ssl-proxy client Exchange-CAS
  match EWS http url /ews.*
    sticky-serverfarm Exchange-CAS-HTTPS-Cookie
    action Exchange-CAS-HTTP
    ssl-proxy client Exchange-CAS
  match ActiveSync http url /Microsoft-Server-ActiveSync.*
    sticky-serverfarm Exchange-CAS-HTTPS-AuthZHeader
    action Exchange-CAS-HTTP
    ssl-proxy client Exchange-CAS
  match OutlookAnywhere http header User-Agent header-value "MSRPC"
    sticky-serverfarm Exchange-CAS-HTTPS-AuthZHeader
    action Exchange-CAS-HTTP
    ssl-proxy client Exchange-CAS
  class Exchange-CAS-HTTPS-RootRequest
    serverfarm Exchange-OWA-REDIRECT
  class class-default
    sticky-serverfarm Exchange-CAS-HTTPS-SourceIP
    action Exchange-CAS-HTTP
    ssl-proxy client Exchange-CAS
This policy map enables SSL decryption, inspection of the URL, and application of the correct load balancing action and stickiness.

 

crypto chaingroup DigiCert
  cert DigiCertRootCA
  cert DigiCertIntermediateCA
  cert mail_contoso_com

access-list all line 10 extended permit ip any any 
access-list all line 20 extended permit icmp any any 

probe https Exchange-OWA
  interval 30
  ssl version all
  request method get url GET /owa/auth/logon.aspx
  expect status 400 404
probe tcp TCP135
  description RPC Endpoint Mapper
  port 135
  interval 30
  connection term forced
probe tcp TCP60000
  description RPC Client Access
  port 60000
  interval 30
  connection term forced
probe tcp TCP60001
  description Address Book Service
  port 60001
  interval 30
  connection term forced

rserver host CAS01
  ip address 192.168.100.101
  inservice
rserver host CAS02
  ip address 192.168.100.102
  inservice
rserver redirect OWA-SSL-REDIRECT
  webhost-redirection https://mail.contoso.com/owa 302
  inservice

serverfarm host Exchange-CAS-HTTPS
  predictor leastconns
  probe Exchange-OWA
  rserver CAS01 443
    inservice
  rserver CAS02 443
    inservice
serverfarm host Exchange-CAS-RPC
  predictor leastconns
  probe TCP135
  probe TCP60000
  probe TCP60001
  fail-on-all
  rserver CAS01
    inservice
  rserver CAS02
    inservice
serverfarm redirect Exchange-OWA-REDIRECT
  rserver OWA-SSL-REDIRECT
    inservice

parameter-map type http Exchange-OWA
  case-insensitive
  persistence-rebalance
  set header-maxparse-length 16384
  set content-maxparse-length 8192
parameter-map type ssl SSL_PARAMS
  cipher RSA_WITH_RC4_128_MD5
  cipher RSA_WITH_RC4_128_SHA
  cipher RSA_WITH_3DES_EDE_CBC_SHA

sticky ip-netmask 255.255.255.255 address source Exchange-CAS-RPC
  timeout 7200
  replicate sticky
  serverfarm Exchange-CAS-RPC
sticky http-cookie Exchange-Sticky Exchange-CAS-HTTPS-Cookie
  cookie insert browser-expire
  replicate sticky
  serverfarm Exchange-CAS-HTTPS
sticky http-header Authorization Exchange-CAS-HTTPS-AuthZHeader
  timeout 7200
  replicate sticky
  serverfarm Exchange-CAS-HTTPS
sticky ip-netmask 255.255.255.255 address source Exchange-CAS-HTTPS-SourceIP
  timeout 7200
  replicate sticky
  serverfarm Exchange-CAS-HTTPS

action-list type modify http Exchange-CAS-HTTP
  header insert request X-Forwarded-For header-value "%is"

ssl-proxy service Exchange-CAS
  key mail_contoso_com
  cert mail_contoso_com
  chaingroup DigiCert
  ssl advanced-options SSL_PARAMS

class-map match-any Exchange-CAS-HTTPS
  2 match virtual-address 192.168.100.200 tcp eq https
class-map type http loadbalance match-any Exchange-CAS-HTTPS-RootRequest
  2 match http url /
class-map match-any Exchange-CAS-RPC
  2 match virtual-address 192.168.100.200 tcp eq 60001
  3 match virtual-address 192.168.100.200 tcp eq 60000
  4 match virtual-address 192.168.100.200 tcp eq 135
class-map match-any Exchange-OWA-REDIRECT
  2 match virtual-address 192.168.100.200 tcp eq www
class-map type management match-any mgmt-cm
  2 match protocol https any
  3 match protocol snmp any
  4 match protocol ssh any
  5 match protocol icmp any

policy-map type management first-match mgmt-pm
  class mgmt-cm
    permit

policy-map type loadbalance first-match Exchange-CAS-HTTPS
  match OWA http url /owa.*
    sticky-serverfarm Exchange-CAS-HTTPS-Cookie
    action Exchange-CAS-HTTP
    ssl-proxy client Exchange-CAS
  match ECP http url /ecp.*
    sticky-serverfarm Exchange-CAS-HTTPS-Cookie
    action Exchange-CAS-HTTP
    ssl-proxy client Exchange-CAS
  match EWS http url /ews.*
    sticky-serverfarm Exchange-CAS-HTTPS-Cookie
    action Exchange-CAS-HTTP
    ssl-proxy client Exchange-CAS
  match ActiveSync http url /Microsoft-Server-ActiveSync.*
    sticky-serverfarm Exchange-CAS-HTTPS-AuthZHeader
    action Exchange-CAS-HTTP
    ssl-proxy client Exchange-CAS
  match OutlookAnywhere http header User-Agent header-value "MSRPC"
    sticky-serverfarm Exchange-CAS-HTTPS-AuthZHeader
    action Exchange-CAS-HTTP
    ssl-proxy client Exchange-CAS
  class Exchange-CAS-HTTPS-RootRequest
    serverfarm Exchange-OWA-REDIRECT
  class class-default
    sticky-serverfarm Exchange-CAS-HTTPS-SourceIP
    action Exchange-CAS-HTTP
    ssl-proxy client Exchange-CAS
policy-map type loadbalance first-match Exchange-CAS-RPC
  class class-default
    sticky-serverfarm Exchange-CAS-RPC
policy-map type loadbalance http first-match Exchange-OWA-REDIRECT
  class class-default
    serverfarm Exchange-OWA-REDIRECT

policy-map multi-match vlan100
  class Exchange-OWA-REDIRECT
    loadbalance vip inservice
    loadbalance policy Exchange-OWA-REDIRECT
  class Exchange-CAS-RPC
    loadbalance vip inservice
    loadbalance policy Exchange-CAS-RPC
    loadbalance vip icmp-reply active
    nat dynamic 1 vlan 1000
  class Exchange-CAS-HTTPS
    loadbalance vip inservice
    loadbalance policy Exchange-CAS-HTTPS
    loadbalance vip icmp-reply active
    nat dynamic 1 vlan 1000
    appl-parameter http advanced-options Exchange-OWA
    ssl-proxy server Exchange-CAS

interface vlan 100
  ip address 192.168.100.10 255.255.252.0
  access-group input all
  nat-pool 1 192.168.100.199 192.168.100.199 netmask 255.255.255.255 pat
  service-policy input mgmt-pm
  service-policy input vlan100
  no shutdown

ip route 0.0.0.0 0.0.0.0 192.168.100.1

Posted Saturday, May 26 2012 by Brian Desmond | Comments
Filed under: Tagged as: , , ,


Setting Static Ports for Exchange Client Access

If you are deploying Exchange in an environment with load balancers or firewalls which aren’t able to handle dynamic RPC port ranges, chances are you’ll be defining static ports for the RPC Client Access Service and the Address Book Service on each CAS server. If you’re using Public Folders, you’ll want a third static port on the Mailbox servers hosting Public Folders. I typically use these ports for this:

  • RPC Client Access Service – TCP 60,000
  • Address Book Service – TCP 60,001
  • RPC Client Access (Public Folders) – TCP 60,002

For the first two, I’ve included a script below which makes quick work of setting the ports. Just run it on the CAS server to make the required changes.

 

param([int32]$MAPIPort = 60000, [int32]$AddressBookPort = 60001, [bool]$RestartServices = $true)
# ==============================================================================================
# NAME: Configure Exchange Static Ports
# 
# AUTHOR: Brian Desmond, brian@briandesmond.com
# DATE  : 4/9/2012
# 
# COMMENT: 
# 
# ==============================================================================================

Set-PSDebug -Strict:$true

function CheckProcessElevation()
{
    $identity  = [System.Security.Principal.WindowsIdentity]::GetCurrent()
    $principal = New-Object System.Security.Principal.WindowsPrincipal($identity)

    return $principal.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)
}

function CreateRegistryKeyIfNecessary([string]$path)
{
    if (Test-Path -Path $path)
    {
        return
    }
    else
    {
        [void](New-Item -Path $path)
    }
}

Function Test-RegistryValue($regkey, $name) 
{
    Get-ItemProperty $regkey $name -ErrorAction SilentlyContinue | Out-Null  
    $?
}

function CreateOrUpdateRegistryValue([string]$path, [string]$valueName, [Microsoft.Win32.RegistryValueKind]$valueType, $value)
{
    if ((Test-Path -Path $path) -ne $true)
    {
        CreateRegistryKeyIfNecessary $path
    }
    
    if ((Test-RegistryValue $path $valueName) -eq $false)
    {
        [void](New-ItemProperty -Path $path -Name $valueName -PropertyType $valueType -Value $value)
    }
    else
    {
        [void](Set-ItemProperty -Path $path -Name $valueName -Value $value)
    }
}

if ((CheckProcessElevation) -eq $false)
{
    Write-Warning "Script must be run from an elevated prompt. Exiting..."
    exit 1
}

$domtParamsPath = "HKLM:\System\CurrentControlSet\Services\MSExchangeAB\Parameters"
$momtParamsPath = "HKLM:\System\CurrentControlSet\Services\MSExchangeRPC\ParametersSystem"

Write-Host "Setting Address Book Service Port to $($AddressBookPort)"
CreateOrUpdateRegistryValue $domtParamsPath "RpcTcpPort" "String" $AddressBookPort.ToString()
Write-Host "Setting RPC Client Access Port to $($MAPIPort)"
CreateOrUpdateRegistryValue $momtParamsPath "TCP/IP Port" "DWord" $MAPIPort

if ($RestartServices)
{
    Write-Host "Restarting Services..."
    Restart-Service -Name "MSExchangeAB" -Confirm:$false
    Restart-Service -Name "MSExchangeRPC" -Confirm:$false
}
Write-Host "Complete." -ForegroundColor Green

 

If you’re looking to restrict the port used for Public Folder access, you’ll need to do this in addition to the script above. The registry setting you want is below:

Key: “HKLM\System\CurrentControlSet\Services\MSExchangeRPC\ParametersSystem”

Value Name: "TCP/IP Port”

Value Type: REG_DWORD

Value Data: “60002” (decimal)

Posted Saturday, May 26 2012 by Brian Desmond | Comments
Filed under: Tagged as: , , , ,


Using Device Manager Remotely

If you’ve got servers running the Server Core version of Windows Server, you’ll probably find yourself needing to look at what devices and drivers are installed at some point. You can do this with various command line tools, but, that’s a non-trivial exercise on a good day. Instead, with a bit of configuration work, you can just use Device Manager remotely.

To do this, you’ll need to configure a Group Policy setting for the affected servers:

Computer Configuration \ Policies \ Administrative Templates \ System \ Device Installation \ "Allow remote access to the Plug and Play interface”

Set the value to enabled:

image

If you don’t do this, you’ll get an error similar to the following:

---------------------------
Device Manager
---------------------------
Unable to access the computer SERVER01
Make sure that this computer is on the network, has remote administration enabled, and is running the "Plug and Play" and "Remote registry" services.

The error was: Access is denied.

---------------------------
OK  
---------------------------

Once you’ve got things in place and the policy is effective, you can use Computer Management to target a remote machine and use the Device Manager snap-in:

---------------------------
Device Manager
---------------------------
Device Manager is running in read-only mode because you are running it on a remote computer. To uninstall devices or to change device properties or drivers, you must run Device Manager on the computer where you wish to make changes.
---------------------------
OK  
---------------------------

You won’t be able to make changes, but, you’ll certainly be able to view all of the relevant details.

Posted Friday, March 16 2012 by Brian Desmond | Comments
Filed under: Tagged as: , , , , ,


Conferences I’ll Be At – 2012 First Half

My calendar is starting to shape up for 2012. If you’re going to be at any IT shows in the first half of the year, here’s where you’ll find me presenting:

TechEd is on the radar for a visit at least, but, not confirmed.

If you’re at any of these shows, stop by and say hello!

Posted Saturday, January 07 2012 by Brian Desmond | Comments
Filed under: Tagged as: ,


2011 in Review

Happy New Years! I’ve put something up here the past couple years as I wrap up and kick off the new year, so I thought I’d do that again. I had the pleasure of visiting customers, presenting at conferences, and taking a couple quick vacations all over the place last year. I managed to stay mostly in the US this year:

image

…save for a couple overseas trips:

image

All told, ~116,406 miles and 90 plane rides.

I sent a mail out to quite a few people who had asked about pictures from all these trips, and I thought I’d share that here – something I’ve not done before.

image

On the road to San Francisco from Eureka, CA in late March. The road signs called for snow chains which our rented Toyota Camry was sorely lacking. Fortunately the snow was light.

image

The Grapevine, driving down the 5 to Los Angeles from Bakersfield, CA.

image

Seals on the beach – driving up Pacific Coast Highway from San Luis Obispo, CA.

image

On the road from San Luis Obispo, CA to Monterey, CA – driving through Big Sur

image

On the road to Monterey

image

The Lone Cypress at Pebble Beach – I had a couple hours to do 17 mile drive before my flight out of Monterey. CA. The airport at Monterey, by the way, has a great little outdoor bar on top of the ramp area.

image

The Concha y Toro vineyard in Santiago, Chile is conveniently accessible from downtown by Subway.

image

Viña del Mar about 1:30 drive outside of Santiago, Chile

image

A somewhat questionable Ascensor I rode down the hill in the port of Valparaiso, Chile

image

Death Valley – the lowest point in the North America.

image

Salt Flats in Death Valley – the land of $5.33/gallon for regular gasoline

image

Another conference week…

image

The Grand Canyon from a Helicopter. Pat Richard and I did this in October – highly recommended.

image

The Hoover Dam, by Helicopter

Happy Trails and Best Wishes for a great 2012!

Posted Saturday, January 07 2012 by Brian Desmond | Comments
Filed under: Tagged as:


Ping a List of Servers with PowerShell

I needed to quickly get the IP addresses of about 100 servers from their names. PowerShell doesn’t appear to have a native Ping cmdlet, but, .Net certainly does. I pasted all the servers into a text file, one per line, and rand the following little loop:

$servers = Get-Content .\serverList.txt
$ping = New-Object System.Net.NetworkInformation.Ping

foreach($s in $servers)
{
    $("$s,$($ping.Send($s).Address)")
}

This loop outputs a comma delimited list of ServerName,IP to the window like this:

TEST-SF6,10.12.3.96
W2003TEST,10.1.34.80
W2003TEST2,10.8.51.27

I pasted the list into a new email in Outlook, highlighted it, and then used the Convert Text to Table feature in Word (and Outlook):

image SNAGHTML3dbfa3a2[4]

Word turned my pasted CSV list into a nice table and I sent it off.

Posted Wednesday, December 28 2011 by Brian Desmond | Comments
Filed under: Tagged as: , ,


Thoughts on Building a Server Image

Repeatable, consistent, and predictable are three things that add an incredible amount of value in IT, and building servers from a base image is one way to deliver on this. I was just replying to a thread on a discussion alias where the person who started the thread had reviewed a blog post (http://www.jasonsamuel.com/2010/05/07/how-to-build-a-vmware-vsphere-vm-template-for-windows-server-2008-r2/) on how to build such an image for VMWare. I and a number of people disputed the recommendations made in the referenced blog post in addition to the various other things the individual who started the thread was planning to install in his image/template.

At a high level, the most important thing from my reply, I think, is that you should not be customizing a server for it to be convenient to your work style. The server is there for a purpose driven task. You shouldn’t even be connected to it via Remote Desktop (or sitting at the console) unless you’re troubleshooting a problem which can only be investigated from the desktop. What this means is that all the little utilities and tweaks you have on your desktop should stay on your desktop. Things like PDF readers, Internet Explorer customizations, screensavers and colors, and taskbar preferences, etc. First and foremost, many of these tweaks are profile specific so when you login with a domain account later, after running sysprep, the tweaks will be gone unless you push them into the default profile and in turn push them on to all users. Secondly, when you move on to the next big opportunity, your successor shouldn’t be expected to inherit and adapt (or spend weeks undoing) your personal preferences.

As far as system settings (e.g. page files, network settings, etc.), tweaking or disabling things just because some random guy on the Internet (including me) told you to is not a great idea. When you install an application from a vendor, be it Microsoft or any third party ISV, chances are they made assumptions in their testing that the OS is in a state relatively close to the default install. When you start disabling services (e.g. Indexing, Print Spooler, etc.) by default in an image, you provide a baseline that doesn’t meet this assumption. Rather than customizing by default, customize for specific applications. The settings in an image should be the ones required to operate at a minimum level of functionality on your network (e.g. maybe you need some custom DNS search suffixes to join the domain or settings to meet security standards). This extends to most any system level default. When you’re looking at changing a default setting, I’d first stop and ask yourself “why?”. What’s the reason this is being changed? Next, consider whether or not it should be or needs to be hardcoded in the image or if you can simply apply that configuration change via Group Policy. Anything hardcoded will require you to come back and update and re-test, and re-release the image when the value needs to be changed, whereas a Group Policy setting is easily tweaked centrally.

Inevitably there are various tools, gadgets, trinkets, etc., which make troubleshooting easier. My experience is that a great many of these tools don’t require installation and will simply run from a network share. Rather than caching tools locally on each server, or installing individual copies, put them out on a share that you can access from any machine. This way you only need to refresh one location when a tool gets updated and you also aren’t installing essentially random software on servers on an as-necessary basis. As soon as those installs aren’t consistent across all servers, you start permuting your test matrix. Personally the only thing I consistently install on a server build is Netmon or Wireshark and occasionally BgInfo (Sysinternals).

Posted Saturday, December 10 2011 by Brian Desmond | Comments
Filed under: Tagged as: