Block direct delivery to @onmicrosoft.com addresses in a hybrid environment

Block direct delivery to @onmicrosoft.com addresses in a hybrid environment

Rate this post

We’re all familiar with how Office 365 tenants work–when you spin up a new Office 365 tenant, you get a managed domain (tenant.onmicrosoft.com).  Then, maybe you configure a hybrid environment, and now your tenant has your domain, as well as your original tenant.onmicrosoft.com domain, and a new tenant.mail.onmicrosoft.com.  The two managed domains–tenant.onmicrosoft.com and tenant.mail.onmicrosoft.com both have internet-routable MX records:

Now, let’s say you’re in a hybrid mail scenario and you have begun synchronizing users and have migrated some mailboxes.  When you synchronize mail-enabled user accounts and migrate mailboxes, your users will get stamped with a tenant address.  Since we already know that the managed domains have their own MX hosts configured, that means that you can deliver mail destined a migrated user (who might have a primary SMTP address of user@customdomain.com) using their onmicrosoft.com address (user@tenant.onmicrosoft.com).

If you have certain mail flow or business requirements (such as DLP, encryption, or other content filtering that has not yet been configured in Office 365) that force your inbound email to traverse a certain path, you may find that unacceptable.  To prevent email delivery directly to the onmicrosoft.com namespace (or any accepted domain in Office 365) directly, you can try a number of different methods.

Transport Rules

TR Option 1

I’ve had some luck with this one in the past, though it seems to be hit or miss and is not as effective as other methods.  You can use a transport rule in your Exchange Online Tenant to attempt to block direct delivery using the following script:

[array]$TenantDomains = (Get-AcceptedDomain | ? { $_.DomainName -like "*onmicrosoft.com" }).Name
New-TransportRule -FromScope NotInOrganization -RecipientDomainIs $TenantDomains -Name "Reject messages to onmicrosoft.com domains" -RejectMessageEnhancedStatusCode 5.7.1 -RejectMessageReasonText "You are not allowed to relay to this user's managed domain name. Please resubmit your message using the recipient's public email address."  -StopRuleProcessing $True

The result when you attempt to send mail to an onmicrosoft.com address in that tenant from a mailbox outside the Exchange organization (either on-premises or in-cloud):

You can see that the status code says 5.7.1 (our status code) and has _ETR appended (meaning it was generated by an Exchange Transport Rule).

However, I’ve recently experienced this one not working so well, so there are some other methods we can employ, each with their own pros and cons.  On to better methods!

TR Option 2

Another method is based on inspecting headers.  Specifically, looking for the Auth-As “Internal” header.  The Auth-As header is stamped in a hybrid configuration so you’ll know if the message is from your “trusted” internal organization.

New-TransportRule -SentToScope InOrganization -Name "Reject messages not routed through MX" -RejectMessageEnhancedStatusCode 5.7.1 -RejectMessageReasonText "You are not allowed to relay directly to this system. Please resubmit your message using the recipient's public email address and/or mail exchanger gateway." -ExceptIfHeaderContainsMessageHeader 'X-MS-Exchange-Organization-AuthAs' -ExceptIfHeaderContainsWords 'Internal' -StopRuleProcessing $True

This method has been more reliable, as it is relying on the destination (SentToScope) in combination with the header that has been stamped by your on-premises mail infrastructure.

TR Option 3

I like to call this the “belt and suspenders” transport rule option.  In addition to looking for the just the Auth-As header, you can configure your on-premises gateway (Exchange or whatever else you’re using) to stamp an additional header on that you can check for.  If you stamp it on your gateway, you’ll still want to stamp it (or verify that it has been stamped) on your Exchange hybrid endpoints relaying to Office 365 to ensure that your internal traffic does not get rejected.  In this example, we’re going to stamp an X-header called “X-PassedThroughOnPremises” with a value of “Yes.”

New-TransportRule -SentToScope InOrganization -Name "Reject messages not routed through MX" -RejectMessageEnhancedStatusCode 5.7.1 -RejectMessageReasonText "You are not allowed to relay directly to this system. Please resubmit your message using the recipient's public email address and/or mail exchanger gateway." -ExceptIfHeaderContainsMessageHeader 'X-MS-Exchange-Organization-AuthAs' -ExceptIfHeaderContainsWords 'Internal' -ExceptIfHeaderMatchesMessageHeader 'X-PassedThroughOnPremises' -ExceptIfHeaderMatchesPatterns 'Yes' -StopRuleProcessing $True

Options 2 and 3 provide the best coverage, but also can cause unsightly NDRs to senders if, for some reason, their outbound MX gateway had been configured to route directly to Office 365.  And we all love support tickets.

On to a slightly more user-friendly method.

Transport Rule-Scoped Connector

I personally think this is one of the best methods to prevent senders from bypassing your MX.  This method employs the transport rule specified in either options 2 or 3 (with a slight modification) in addition to a connector to ensure traffic is rerouted to the appropriate MX host.

In this example, you own contoso.com, and your on-premises mail gateway is gateway.contoso.com.  You’re going to use your on-premises system to stamp the header “X-PassedThroughOnPremises” with a value of “Yes,” check for the presence of that header, and resubmit the message to the specified gateway if it’s not present. And, to make sure it processes everything, we’re going to assign it Priority 0 (moving it to the top of the list).

Run this in the Exchange Online PowerShell.

[array]$TenantDomains = (Get-AcceptedDomain).Name
New-OutboundConnector -Name "Reroute to MX Connector" -IsTransportRuleScoped $true -UseMXRecord $false -SmartHosts 'gateway.contoso.com'
New-TransportRule -Name "Reroute to MX" -RecipientDomainIs $TenantDomains -RouteMessageOutboundConnector 'Reroute to MX Connector' -ExceptIfHeaderContainsMessageHeader 'X-MS-Exchange-Organization-AuthAs' -ExceptIfHeaderContainsWords 'Internal' -ExceptIfHeaderMatchesMessageHeader 'X-RoutedThroughOnPremises' -ExceptIfHeaderMatchesPatterns 'Yes' -StopRuleProcessing $true -Priority 0

Run this in the Exchange Management Shell on-premises.

New-TransportRule -SetHeaderName 'X-PassedThroughOnPremises' -SetHeaderValue 'Yes' -Name 'Passed Through On-Premises' -StopRuleProcessing:$false -Mode 'Enforce' -Comments 'Set X-PassedThroughOnPremises header to Yes on all messages'
' -RuleErrorAction 'Ignore' -SenderAddressLocation 'Header' -Priority 0

Don’t be a reject.  Be a resubmit.

Reader Comments

  1. The only issue I see with the last transport rule is if Microsoft is marked as a trusted sender on your gateway (and it probably is) then the email coming from Microsoft will not be thoroughly scanned for malware/spam (or not at all). This could be used as a back door spam or phishing method.

    1. The only thing the last rule is doing is stamping mail that has arrived at your on-premises Exchange server has having been received there. In order to get that transport rule applied, it would have had to pass through your on-premises gateway. If you have a requirement to make sure mail only ingresses through one entry point (on-premises MX), you’re going to have your MX pointed to that destination. More than likely, your on-premises first-hop gateway won’t be accepting mail for @mail.onmicrosoft.com addresses.

      All content (regardless of origin) is scanned for malware before it enters Office 365. It cannot be bypassed. If mail has originated on-premises and is passing through your hybrid connector to Office 365, it’s already been marked as AuthAs:Internal in the headers anyway. This transport rule happens before that rule gets applied, and has no bearing on that. The only thing the last transport rule does is check to see if that header is present as evidence of having been routed through your on-premises environment. If it’s not present, your mail is going to get rejected/redirected to the public MX and then start the process over. If we never stamped it, it would continue in that same loop until the hop count exceeded.

  2. Hi Aaron, I was reading this article and would like to know how to setup the “X-PassedThroughOnPremises” with a value of “Yes” part. Could you clarify this? Thanks, Bas

    1. You’ll want to add a transport rule on-premises using something like this:

      New-TransportRule -SetHeaderName ‘X-PassedThroughOnPremises’ -SetHeaderValue ‘Yes’ -Name ‘Passed Through On-Premises’ -StopRuleProcessing:$false -Mode ‘Enforce’ -Comments ‘Set X-PassedThroughOnPremises header to Yes on all messages’
      ‘ -RuleErrorAction ‘Ignore’ -SenderAddressLocation ‘Header’

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.