The topic of shared hosting with Exchange Server is not new. Whether your interest is to accommodate more than 1 company with a simple Exchange configuration, as a result of a merge or acquisition, or to start your own small e-mail hosting business, Exchange Server has all the power to respond to your needs.

Since I like to write about the most common requests I get in my technical community life, I thought it would be interesting to detail the setup configuration for a scenario of an Exchange infrastructure shared by more than one customer/company. So for all of those who would like to start a hosting business, I recommend a further advanced solution, Hosted Messaging and Collaboration (HMC) version 4.0, which I'll cover lightly in this article.

Depending on your needs, there is more than one way of achieving shared hosting: with a simple configuration (Figure 1), with a more complex configuration (Figure 2) or by using the HMC framework (Figure 3). Exchange is really versatile and scales according to your goals.


Figure 1: Simple Exchange Server 2007 Organization


Figure 2: Complex Exchange Server 2007 Organization


Figure 3: HMC Architecture

For the purpose of this article, I'll detail the required steps for the simple configuration with a single server. If you ever need a more complex configuration, the necessary modifications won't be difficult to infer.

Disclaimer

The following article seriesdetails a configuration which is not officiallysupported by Microsoft. You can read the official documentation at the following link: Configuring Virtual Organizations and Address List Segregation in Exchange 2007.

Main Objectives

The main goals we're trying to accomplish are:

  • SMTP Domain acceptance;
  • Isolation from other customers/companies;
  • Differentiated Address Lists;
  • Exchange 2007 connection protocols: MAPI, Outlook Anywhere and OWA.

Solution Topology

The tested scenario consisted of a single server with the Client Access, Hub Transport and Mailbox roles. I then used a client computer that belongs to the domain and an external one that simulates access through the Internet.


Figure 4

In order to illustrate the desired configuration, I built a scenario where I was the System Administrator of my own hosting company, and I serviced some of the most famous secret agencies around the world.

For this article I'll use the 2 spy agencies of the old TV series Get Smart: CONTROL and KAOS. These 2 organizations must not know the presence of each other on the same server, so I better do my job right!


Figure 5: CONTROL Agents

Organization / Agents
CONTROL /
  • Maxwell Smart [
  • Agent 99 [

KAOS /
  • Mr. Big [
  • Groovy Guru [

Setting Up the Environment

So let's start by organizing our Active Directory. Since probably there will be lots of permissions and rights involved, it's better to create a proper OU hierarchy and I bet a Security Group for each Organization will be very helpful.

I created a top level OU called Hosting, under which we'll create a new OU for every Organization that is supposed to be hosted (Figure 6). Under each Organization OU, I like to separate Users and Groups, but it isn't strictly necessary to do it this way.


Figure 6

Since we need a mail enabled group, we'll use the Exchange Management Console (EMC). Just expand Recipient Configuration, select Distribution Group and on the Actions pane hit New Distribution Group. Select Security as the Group Type and populate the remaining fields according to your Organization. Don't forget to select the right OU (Figure 7). Then just click Next and New. Of course, this and most of the procedures of this article can be done using PowerShell. Just before clicking Finish, the EMC will show you the PowerShell command equivalent (Figure 8).


Figure 7


Figure 8

Since we don't want our hosted companies to use the AD Domain name (mydomain.local), it's better to add the proper UPN suffixes, so that users can use these to log on. Open the Active Directory Domains and Trusts management console, right click Active Directory Domains and Trusts and select Properties. You'll be presented with a window where you can insert all the alternative UPN suffixes you want (Figure 9).


Figure 9

Hub Configuration

Let's look at how to configure the Hub Transport for the hosting organization. The first thing we want to do is add the hosted SMTP addresses as internal domains.

This can be achieved using the EMC, expanding Organization Configuration, Hub Transport and then clicking on the Accepted Domains tab. Then, on the Actions pane, click New Accepted Domain. This will kick the New Accepted Domain Wizard. Just fill the text boxes accordingly and make sure that Authoritative Domain. E-mail is delivered to a recipient in the Exchange organization is selected (Figure 10).

Click Next, review the completion summary and the PowerShell equivalent command, and close the window by clicking Finish (Figure 11).

Repeat these same steps for the KAOS organization and any other hosted companies you like.


Figure 10


Figure 11

Now that the required SMTP domains are accepted as internal, let's define a new e-mail address policy, so that the new users are automatically assigned their right e-mail address.

Since we want the e-mail addresses to be generated automatically for our recipients, we must figure out some kind of rule to achieve this objective. My first thought was to use a Distribution or Security Group, and make the e-mail address policy apply by group membership. I even built the necessary PowerShell command (Figure 12). Unfortunately, for Exchange 2007 RTM, filtering by group membership does not work in all cases. This is a bug that will be fixed in SP1.


Figure 12

The next logical choice was to use the attribute Company. But since this attribute isn't available for groups, and we also want them to be assigned a proper e-mail address, the final solution was to use Custom Attribute 1.

If you didn't close EMC since the last step, select the E-mail Address Policies tab, and click New E-mail Address Policy from the Actions pane. Give it a name for future reference and click Next (Figure 13).


Figure 13

Select Custom Attribute 1 equals Value, click the specified hyperlink and type the text value that will identify each hosted organization. For the current example we'll use "CONTROL" (Figure 14).


Figure 14

On the next screen, click Add, select the E-mail address local part (I used first name and last name initial) and the E-mail address domain (control.org), as depicted in Figure 15 and Figure 16. Click Next and the Finish on the completion summary (Figure 17). Create another E-mail address policy for KAOS organization and you'll end up with the necessary policies created as illustrated in Figure 18.


Figure 15


Figure 16


Figure 17


Figure 18

Figure 19 shows the 2 CONTROL agents with the correct e-mail address, after we applied the CONTROL e-mail address policy.


Figure 19

Mailbox Configuration

Now we want to provision each hosted organization with their own address list. The procedures are somewhat similar to the E-mail address policy creation. We'll use Custom Attribute 1 again to filter the pertinent recipients.

Open EMC, expand Organization Configuration, select the Address Lists tab and then click New Address List on the Actions pane. Give it the name you want (CONTROL AL) and select the recipient type (Figure 20). Click Next.


Figure 20

As I said, we'll use Custom Attribute 1, so once again select Custom Attribute 1 equals Value, click the specified hyperlink and type the text value that will identify each hosted organization (CONTROL or KAOS), as seen on Figure 21. Click Next and then Finish to end the address list creation process (Figure 22).

After you repeat the same steps for KAOS organization, the Address Lists tab will look like Figure 23.


Figure 21


Figure 22


Figure 23

Let's move on to the offline address book creation. With Mailbox selected on the left pane, click on the Offline Address Book tab. From the Actions pane, click New Offline Address Book. This will pop up the New Offline Address Book wizard (Figure 24), where you first must select the generation server, give it a proper name and include an address list you previously created (CONTROL AL in the illustrated case). Click Next, add the OAB virtual directory and select Enable Web-based distribution and Enable public folder distribution (Figure 25). Click Finish to close the wizard (Figure 26).

Figure 27 depicts how Offline Address Book tab looks after creating the OAB for CONTROL and KAOS.


Figure 24


Figure 25


Figure 26


Figure 27

And last but not least, to end our Mailbox configuration, we must create different Global Address Lists (GAL) for each spy agency.

To complete this step we'll use PowerShell. You cannot use the Exchange Management Console to create a GAL. You must use the New-GlobalAddressListcmdlet in the Exchange Management Shell (Figure 28):

New-GlobalAddressList –Name “CONTROL GAL” -RecipientFilter {(Alias –ne $null –and CustomAttribute1 –eq ‘CONTROL’ –and(ObjectClass –eq ‘user’ –or ObjectClass –eq ‘contact’ –or ObjectClass –eqmsExchSystemMailbox –or ObjectClass –eq ‘msExchDynamicDistributionList’ –or ObjectClass –eq ‘group’))}


Figure 28

If you have multiple GALs in your organization, only one GAL is displayed in the Outlook Address Book on a client computer. This address list displays as Global Address List, even if you specified a different name when creating it in Exchange Server 2007. We'll see further ahead how to associate each GAL for the different hosted organizations.

Update each Address list by using "Update-AddressList "CONTROL AL"

Next

Update the GAL by using “Update-GlobalAddressList “CONTROL GAL”

Hiding Address Lists

This is really the tricky part of a hosting solution with Exchange 2007. Exchange Server 2007 scales very well to thousands of mail enabled objects, so it's not a question of size. The difficult part is isolating each hosted organization in order to give them a user experience as if they were the only organization on the server.

What we did in Part 1 of this article was to create different address lists and to assign each mail enabled object its own e-mail address policy. If we did nothing else, the user would see everyone else hosted on the server when he or she used Outlook (Figure 1). The desired scenario is a complete isolation of the address lists. We want our Maxwell Smart to only see the other CONTROL Agents, as illustrated in Figure 2.

And how do we accomplish this? By playing around with ADSI Edit and ACLs and using some non-standard procedures that Microsoft neither recommends nor supports. But since I'm writing for academic purposes, I'll show you how.


Figure 1


Figure 2

Active Directory Object Permissions Quick Tutorial

The most common read permissions (List Contents, Read All Properties, and Read Permissions) are usually enough to cover most scenarios, but for our slightly advanced configuration we'll need to use a less known permission: List Object. Figure 3, taken from ADSI Edit, illustrates the advanced security properties of an Active Directory object.


Figure 3

To enable the List Object functionality, you must modify the dSHeuristics property (using ADSI Edit,) of the object CN=Directory Service, CN=Windows NT, CN=Services, CN=Configuration, DC=mydomain, DC=local (Figure 4). The property uses string syntax and by default the value is not set, but its internal default is 0. The dSHeuristics is a Unicode string in which each character contains a value for a single domain-wide setting. The third character from left controls the List Object functionality. In other words, to enable it, you must write 001 into the dSHeuristics property (Figure 5).


Figure 4


Figure 5

While the List Contents permission allows viewing of all immediate child objects, using List Object allows hiding some of them. If someone doesn't have List Contents to the parent object, List Object can be used to grant him permission to see the existence of individual child objects. That user sees only those child objects for which he has the List Object permission and the remaining child objects are invisible to him.

Note:
For the List Object permission to work, you must grant it also for the parent object. Consequently, you must block permission inheritance of those child objects that you want to make invisible by removing List Object from them. Modifying the dsHeuristics property can greatly increase the number of access check calls that are made, and can have a significant negative effect on performance.

For more information on this subject, please read Controlling Object Visibility.

Modifying Permissions for the Address Lists Containers

WARNING!:
THE FOLLOWING PROCEDURES ARE NEITHER SUPPORTED NOR RECOMMENDED BY MICROSOFT!

We'll use ADSI Edit from the Windows 2003 Support Tools to tweak the permissions of the Address Lists containers (All Global Address Lists, All Address Lists and the Offline Address Lists) and sub containers.

The procedure consists of the following steps:

Containers

  • Remove Permissions Inheritance for All Address Lists, All Global Address Lists, Offline Address Lists;
  • In the Security tab, remove the Anonymous Logon, Everyone and Authenticated Users;
  • Add Authenticated Users and grant them List object so they can access the folders below containing their own address lists (using PowerShell).

Address Lists

  • Remove Permissions Inheritance for each Address List, GAL and OAB we created;
  • Remove Authenticated Users from the Security tab;
  • Add the appropriate permissions for each list, so that only one organization can read them.
  1. So, let's start by running ADSI Edit, expand Configuration | CN=Configuration,DC=mydomain,DC=local | CN=Services | CN=Microsoft Exchange | CN=My Organization| CN=Address Lists Container, right click CN=All Address Lists and select Properties (Figure 6).


Figure 6

  1. Go to the Security tab, click Advanced and deselect Allow inheritable permissions from the parent to propagate to this object... (Figure 7). After clicking OK, select Copy on the Security warning (Figure 8). Some other warnings will pop up, select Yes in all of them (Figure 9, Figure 10).


Figure 7


Figure 8


Figure 9


Figure 10

  1. Back at the Security tab, remove the Anonymous Logon, Everyone and Authenticated Users and click OK.
  2. Repeat steps 1-3 for All objects in the following containers CN=Global Address Lists, CN=Offline Address Lists, and CN=Default Global Address List, CN=All Global Address Lists

To be clear, do this for CN=user, CN=contacts, etc..

  1. Add the List Object permission for Authenticated Users. In order to automate this task, let's use some PowerShell commands (Figure 11):
    $container = "CN=All Global Address Lists,CN=Address Lists Container,CN=My Organization,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=mydomain,DC=local"
    Add-ADPermission -Identity $container -User "Authenticated Users" -AccessRightsListObject
    $container = "CN=All Address Lists,CN=Address Lists Container,CN=My Organization,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=mydomain,DC=local"
    Add-ADPermission -Identity $container -User "Authenticated Users" -AccessRightsListObject
    $container = "CN=Offline Address Lists,CN=Address Lists Container,CN=My Organization,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=mydomain,DC=local"
    Add-ADPermission -Identity $container -User "Authenticated Users" -AccessRightsListObject


Figure 11

  1. Let's move on to the lists we previously created. Repeat steps 1-2 for each Address List, Global Address List and Offline Address List created for our spy agencies.
  2. For each of the previously mentioned lists, remove Authenticated Users from the Security tab.
  3. Add appropriate permissions for each list, so that only one organization can read its own list. We can use the following PowerShell commands (Figure 12):
    $container = "CN=KAOS GAL,CN=All Global Address Lists,CN=Address Lists Container,CN=My Organization,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=mydomain,DC=local"
    Add-ADPermission $container -User "KAOS Agents" -AccessRightsGenericRead, ListChildren -ExtendedRights Open-Address-Book
    $container = "CN=KAOS AL,CN=All Address Lists,CN=Address Lists Container,CN=My Organization,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=mydomain,DC=local"
    Add-ADPermission $container -User "KAOS Agents" -AccessRightsGenericRead, ListChildren -ExtendedRights Open-Address-Book
    $container = "CN=KAOS OAB,CN=Offline Address Lists,CN=Address Lists Container,CN=My Organization,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=mydomain,DC=local"
    Add-ADPermission $container -User "KAOS Agents" -AccessRightsGenericRead, ListChildren -ExtendedRights ms-Exch-Download-OAB


Figure 12

Additional Active Directory Tweaks

With the right permissions in place, the correct Global Address List for each hosted company will be displayed. But for the general Address List and Offline Address Book, further Active Directory tweaking is necessary.

For the Address Lists, we must add each distinguished name to the addressBookRoots attribute of CN=Microsoft Exchange, CN=Services, CN=Configuration, DC=mydomain, DC=local.

In order to do this, we can edit the properties of each address list and copy the distinguishedName attribute value (Figure 13). Next, right click CN=Microsoft Exchange, select Properties (Figure 14) and add the previously copied value to addressBookRoots. Repeat these steps for each address list. Figure 15 depicts all the address book roots that Exchange will use (All Address Lists, CONTROL AL and KAOS AL).REMOVE THE Entry: CN=ALL ADDRESS LISTS…. Otherwise OAB generation will fail.


Figure 13


Figure 14