Cross-Forest Trust Types in Active Directory

Active Directory supports multiple types of trust relationships that allow users in one domain or forest to access resources in another. Understanding the distinctions between trust types is essential before creating one, as the wrong type will either fail to install or fail to provide the access required.

A Forest Trust is a transitive, two-way (or one-way) trust between two complete AD forests. It allows every domain in one forest to trust every domain in the other forest. Forest trusts require both forests to be at the Windows Server 2003 forest functional level or higher. This is the appropriate trust type when you need broad access between two organizations or divisions with separate AD forests.

An External Trust is a non-transitive trust between a specific domain in one forest and a specific domain in another forest (or a Windows NT 4.0 domain). Unlike forest trusts, external trusts do not extend to other domains in either forest. Use external trusts when you need access between two specific domains without enabling forest-wide trust, or when targeting legacy NT 4.0 domains.

A Shortcut Trust is an explicit trust between two domains within the same forest that shortens the Kerberos authentication path. In large, deep forest hierarchies, cross-domain authentication normally traverses the entire trust path up to the forest root and back down. A shortcut trust creates a direct authentication path, reducing latency.

A Realm Trust connects an AD domain or forest with a non-Windows Kerberos realm (such as MIT Kerberos on Linux). It can be transitive or non-transitive and one-way or two-way.

Prerequisites: DNS Resolution Between Forests

Before creating any cross-forest trust, both forests must be able to resolve each other’s DNS names. This is the single most common prerequisite that is missing or misconfigured. DNS resolution can be established through several methods:

Conditional forwarders are the most common and simplest approach. Each forest’s DNS servers forward queries for the other forest’s namespace to that forest’s DNS servers:

# On the DNS servers in Forest A (corp.example.com), forward queries for Forest B (partner.org)
# Run on each DNS server in Forest A:
Add-DnsServerConditionalForwarderZone `
    -Name "partner.org" `
    -MasterServers "10.20.1.5","10.20.1.6" `
    -ReplicationScope Domain `
    -PassThru

# On the DNS servers in Forest B (partner.org), forward queries for Forest A:
Add-DnsServerConditionalForwarderZone `
    -Name "corp.example.com" `
    -MasterServers "10.10.1.5","10.10.1.6" `
    -ReplicationScope Domain `
    -PassThru

# Verify DNS resolution from each forest to the other
# From a server in Forest A:
Resolve-DnsName "partnerdc01.partner.org" -Server "10.10.1.5"
nslookup partnerdc01.partner.org 10.10.1.5

# From a server in Forest B:
Resolve-DnsName "hqdc01.corp.example.com" -Server "10.20.1.5"

# Test SRV records (needed for Kerberos and DC location)
nslookup -type=srv _ldap._tcp.dc._msdcs.partner.org 10.10.1.5
nslookup -type=srv _kerberos._tcp.dc._msdcs.corp.example.com 10.20.1.5

Alternatively, you can use DNS stub zones or secondary zones. Stub zones replicate only the NS and SOA records of the other zone, automatically updating when the other forest adds or changes DNS servers — making them more resilient to infrastructure changes than static conditional forwarders.

# Create a stub zone instead of a conditional forwarder
Add-DnsServerStubZone `
    -Name "partner.org" `
    -MasterServers "10.20.1.5" `
    -ReplicationScope Forest `
    -PassThru

Creating a Forest Trust via Active Directory Domains and Trusts

The Active Directory Domains and Trusts MMC console (run domain.msc) provides a wizard-driven interface for creating trust relationships. To open the trust creation wizard, right-click on your forest root domain and select Properties > Trusts tab > New Trust.

For a forest trust, the wizard walks you through:

  1. Specifying the name of the other forest’s root domain
  2. Selecting “Forest trust” as the trust type
  3. Choosing the direction (one-way: incoming, one-way: outgoing, or two-way)
  4. Specifying whether this side only or both sides are created now (creating both sides requires credentials for the other forest)
  5. Selecting the authentication scope (Forest-wide or Selective)
  6. Setting the trust password (used to establish the initial trust relationship)

After completing the wizard, verify the trust from both sides using the built-in trust verification button, then confirm with nltest.

Creating a Forest Trust with PowerShell

The New-ADTrust cmdlet creates trust relationships from PowerShell. You must run this on a domain controller (or from a machine with the RSAT AD DS tools) in the forest where you want to create the trust object.

# Create a two-way forest trust from Forest A to Forest B
# Run with Enterprise Admin credentials for Forest A
# You will need Enterprise Admin creds for Forest B as well

# First, get the credential object for the remote forest admin
$remoteCred = Get-Credential -Message "Enter Enterprise Admin credentials for partner.org"

# Create the trust (this creates it on both sides if you provide the remote credentials)
New-ADTrust `
    -Name "partner.org" `
    -TrustType External `
    -Direction Bidirectional `
    -TrustingPassword "Tr@stP@ssw0rd2024!" `
    -Credential $remoteCred `
    -SourceName "corp.example.com" `
    -TargetName "partner.org"

# For a Forest Trust (vs External Trust):
New-ADTrust `
    -Name "partner.org" `
    -TrustType Forest `
    -Direction Bidirectional `
    -TrustingPassword "Tr@stP@ssw0rd2024!" `
    -Credential $remoteCred

# Create a one-way incoming trust (users in partner.org can access resources in corp.example.com)
New-ADTrust `
    -Name "partner.org" `
    -TrustType Forest `
    -Direction Inbound `
    -TrustingPassword "Tr@stP@ssw0rd2024!" `
    -Credential $remoteCred

# List existing trusts
Get-ADTrust -Filter * | Select-Object Name, TrustType, Direction, `
    TrustAttributes, IntraForest | Format-Table -AutoSize

Trust Transitivity and One-Way vs Two-Way Trusts

Understanding trust direction and transitivity prevents access control mistakes. In a two-way trust, users from either forest can be granted access to resources in the other forest. In a one-way trust, only users from the trusted forest can access resources in the trusting forest.

Memory aid: think of it as “the trusting domain trusts the trusted domain”. If Forest A trusts Forest B (one-way outbound from A’s perspective), users from Forest B can authenticate to resources in Forest A.

Transitivity in forest trusts means that if Forest A has a forest trust with Forest B, and Forest B has a forest trust with Forest C, Forest A and Forest C do NOT automatically trust each other — forest trusts are not transitive beyond the two forests involved. You must create a direct trust between A and C if cross-forest access is needed.

# Verify trust properties
Get-ADTrust -Identity "partner.org" | Select-Object Name, Direction, `
    TrustType, TrustAttributes, IntraForest, IsTreeRoot, IsTreeParent | `
    Format-List

# TrustAttributes values:
# 0x1  = Non-transitive (external trust)
# 0x8  = Forest trust
# 0x20 = Cross-organization (selective authentication)
# 0x40 = Forest-wide authentication within same org

Selective Authentication vs Forest-Wide Authentication

Authentication scope is a critical security decision when creating cross-forest trusts. Forest-wide authentication (the default for forest trusts between organizations in the same company) allows any user from the trusted forest to automatically authenticate to any resource in the trusting forest, subject only to the access control lists on those resources.

Selective authentication is more restrictive and is recommended for trusts with external organizations or partner companies. With selective authentication, users from the trusted forest can only access specific resources where they have been explicitly granted the Allowed to authenticate permission on the computer object in the trusting forest.

# Enable selective authentication on an existing trust
# Set via the trust's Authentication property
Set-ADTrust -Identity "partner.org" `
    -SelectiveAuthentication $true

# Verify selective authentication is enabled
Get-ADTrust -Identity "partner.org" | Select-Object Name, SelectiveAuthentication

# After enabling selective authentication, you must explicitly grant
# "Allowed to authenticate" on each computer object that trusted users need to access:
# In Active Directory Users and Computers, on the target computer object:
# Security tab > Add trusted user/group > check "Allowed to authenticate"

# PowerShell: Grant Allowed to Authenticate permission on a specific server
$computer = Get-ADComputer -Identity "SQLSERVER01"
$acl = Get-ACL -Path "AD:$($computer.DistinguishedName)"

# Get the trusted user or group from the other forest
$trustee = New-Object System.Security.Principal.NTAccount("PARTNERAllPartnerUsers")
$accessRule = New-Object System.DirectoryServices.ActiveDirectoryAccessRule(
    $trustee,
    [System.DirectoryServices.ActiveDirectoryRights]::ExtendedRight,
    [System.Security.AccessControl.AccessControlType]::Allow,
    [GUID]"68B1D179-0D15-4D4F-AB71-46152E79A7BC"  # Allowed to Authenticate GUID
)

$acl.AddAccessRule($accessRule)
Set-ACL -Path "AD:$($computer.DistinguishedName)" -AclObject $acl

SID Filtering and Trust Quarantine

SID filtering (also called SID quarantine) is a security mechanism that prevents users in a trusted forest from using SID History attributes to claim additional privileges in the trusting forest. When enabled, the trusting forest strips any SIDs from non-trusted namespaces from Kerberos tickets.

SID filtering is enabled by default on external trusts and on forest trusts with external organizations. For internal forest trusts within the same organization, SID history may need to be allowed during domain migrations.

# Check current SID filtering status
netdom trust corp.example.com /domain:partner.org /quarantine /verify

# Enable SID filtering (quarantine) on a trust - the default for external orgs
netdom trust corp.example.com /domain:partner.org /quarantine:yes

# Disable SID filtering (only do this for trusted internal forests during migration)
# WARNING: Disabling SID filtering is a significant security risk with external orgs
netdom trust corp.example.com /domain:partner.org /quarantine:no

# Also check via PowerShell
Get-ADTrust -Identity "partner.org" | Select-Object Name, SIDFilteringForestAware, SIDFilteringQuarantined

Routing Name Suffixes

Name suffix routing controls which UPN suffixes and DNS names are routed through a specific trust. By default, a forest trust routes all UPN suffixes registered in the trusted forest. If the trusted forest has additional UPN suffixes (e.g., alternative email-format UPNs), those must be explicitly enabled for routing.

# View all name suffixes being routed via a trust
netdom trust corp.example.com /domain:partner.org /namesuffixes

# Enable routing for a specific UPN suffix in the trusted forest
netdom trust corp.example.com /domain:partner.org `
    /namesuffixes /enablesuffix:partner-alt.com

# Disable routing for a suffix (block it)
netdom trust corp.example.com /domain:partner.org `
    /namesuffixes /disablesuffix:partner-old.com

# PowerShell: Get name suffix routing configuration
Get-ADTrustAdditionalNameSuffix -Filter * | Select-Object Name, Status, UPN

Testing the Trust with nltest

The nltest command-line tool verifies the trust relationship and tests the secure channel between domain controllers in both forests:

# Verify the trust secure channel exists between the two forests
nltest /sc_verify:partner.org

# Output indicates success if:
# "Flags: 0 WRITEABLE HAS_IP HAS_TIMESERV"
# "Trusted DC Name \partnerdc01.partner.org"
# "The command completed successfully"

# Get the domain information across the trust
nltest /domain_trusts /all_trusts

# Test that you can query the remote forest's DC
nltest /dsgetdc:partner.org /force

# Verify the trust from the remote forest side
# Run on a DC in partner.org:
nltest /sc_verify:corp.example.com

# Test Kerberos ticket acquisition for a cross-forest resource
# Using klist on a test machine that has authenticated cross-forest:
klist tickets
klist tgt

# Request a specific cross-forest service ticket
klist get krbtgt/[email protected]

Cross-Forest Kerberos Authentication Flow

Understanding how cross-forest Kerberos authentication works helps diagnose failures. When a user in Forest A attempts to access a resource in Forest B:

  1. The user’s DC in Forest A issues a referral ticket pointing to Forest A’s forest root DC
  2. Forest A’s forest root DC issues a cross-realm referral ticket for Forest B’s forest root domain
  3. Forest B’s forest root DC issues a referral to the specific domain in Forest B that hosts the resource
  4. The resource domain DC issues the final service ticket

This multi-hop process means network connectivity and DNS must work at each step:

# Verify cross-forest group membership works (add partner user to a local group)
# On a server in Forest A:
$partnerUser = "PARTNERJohnDoe"
$localGroup = "CORPResourceAccessGroup"
Add-ADGroupMember -Identity $localGroup -Members $partnerUser

# Cross-forest group membership has limitations:
# - You CANNOT add cross-forest users to Domain Local groups in their own forest 
#   and have them work cross-forest (they work locally only)
# - You CAN add cross-forest principals to resource domain's local groups
# - Universal groups from a trusted forest CAN be added to resource domain local groups

# List members of a group including cross-forest members
Get-ADGroupMember -Identity "ResourceAccessGroup" -Recursive | `
    Select-Object Name, objectClass, distinguishedName

Cross-Forest Group Membership Limitations

Cross-forest trusts have specific constraints around group nesting and membership that differ from intra-forest group behavior:

  • Universal groups from a trusted forest can be added to local domain groups in the resource forest
  • Global groups from a trusted forest can only be added to universal groups or used directly in ACLs, not nested into resource forest global groups
  • You cannot add users from Forest B into Global or Universal groups in Forest A — only into Domain Local groups (for ACLs) or Universal groups exposed at the forest boundary
  • Token bloat can occur when users have cross-forest group memberships, as SIDs from the trusted forest are included in the Kerberos PAC — large numbers of group memberships can cause authentication failures due to the Kerberos token size limit
# Check for potential Kerberos token size issues for cross-forest users
# Estimate the number of group memberships (each SID adds ~40 bytes to the PAC)
$user = Get-ADUser -Identity "JohnDoe" -Server "partnerdc01.partner.org" `
    -Properties MemberOf
$groupCount = ($user.MemberOf).Count
Write-Host "Group memberships: $groupCount"
Write-Host "Estimated PAC size addition: $($groupCount * 40) bytes"
# Default Kerberos token size limit: 48KB (65,535 bytes with MaxTokenSize setting)

# Increase MaxTokenSize if needed (requires reboot)
# HKLMSYSTEMCurrentControlSetControlLsaKerberosParameters
Set-ItemProperty -Path "HKLM:SYSTEMCurrentControlSetControlLsaKerberosParameters" `
    -Name "MaxTokenSize" -Value 65535 -Type DWord

Trust Monitoring and Maintenance

Cross-forest trusts require ongoing monitoring. The trust password is automatically changed every 30 days by the domain controllers. Monitoring should confirm the trust is healthy and secure channels remain intact:

# Schedule a regular trust health check
# Check trust status on all domain controllers
$allDCs = Get-ADDomainController -Filter *
foreach ($dc in $allDCs) {
    Write-Host "Checking trust from $($dc.Name)..."
    Invoke-Command -ComputerName $dc.Name -ScriptBlock {
        nltest /sc_verify:partner.org
    } -ErrorAction Continue
}

# Monitor trust-related event log entries
Get-WinEvent -LogName "System" -MaxEvents 100 | `
    Where-Object { $_.Id -in (5705, 5706, 3210, 5722) } | `
    Select-Object TimeCreated, Id, Message | Format-List

# Key event IDs for trust issues:
# 5705 - The password for account DOMAINMACHINENAME$ was changed
# 3210 - This computer could not authenticate with DC
# 5722 - The session setup from the computer failed to authenticate

# Reset the trust password manually if secure channel is broken
netdom trust corp.example.com /domain:partner.org /resetpwd /userD:Administrator `
    /passwordD:* /userO:PARTNERAdministrator /passwordO:*

# Force a trust verification check (same as clicking Validate in GUI)
netdom trust corp.example.com /domain:partner.org /verify

# View trust object metadata in AD
Get-ADObject -Filter { objectClass -eq "trustedDomain" } `
    -SearchBase "CN=System,DC=corp,DC=example,DC=com" `
    -Properties * | Select-Object Name, TrustDirection, TrustType, `
    TrustAttributes, WhenChanged, WhenCreated | Format-Table -AutoSize

Cross-forest trusts in Active Directory provide a controlled, manageable way to enable resource sharing between separate AD forests. The key to a successful deployment is thorough DNS preparation, deliberate selection of authentication scope (strongly prefer selective authentication for external organizations), and ongoing monitoring of secure channel health across all domain controllers in both forests.