Learn F5 Technologies, Get Answers & Share Community Solutions Join DevCentral

Questions and Answers


Loading

Submitting

Blocking iOS 6.1 Devices on Exchange 2010

question

This is more informative, the last few hours we started experenceing issues with Apple iOS 6.1, essentially malformed meetings on a device cause the device to get into a sync loop which causes excessive transaction log growth on the Exchange mailbox servers which will cause Exchange performance issues and potentially transaction log drives to run out of disk space.

Exchange has a limited ability in blocking options when using the internal blocking features users are presented with "Your password may be incorrect", however this solution provides a simple "The server refused connection" as an alternative, this was added to our previous /microsoft-server-activesync irule.

 

if {[HTTP::header "User-Agent"] matches_regex {^Apple.*1002.*}} {

    reject

  }

 

 

-Dan

39 Answer(s):

Hi Dan,

Thanks for the info. I thought the main iOS 6 bug with Exchange meetings was fixed in 6.0.1. Are you still seeing issues with iOS 6.1 clients?

http://news.cnet.com/8301-13579_3-57543794-37/apple-releases-ios-6.0.1-with-over-the-air-update-tool/

Aaron

Hi Aaron,

This is a newly discovered issue with iOS 6.1, more details (http://www.windowsitpro.com/blog/tony-redmonds-exchange-unwashed-50/exchange-server/apple-ios-61-upgrade-excessive-transaction-log-growth-145223)

Subsequently we have re-opened our environment to iOS 6.1 devices but disable the Meeting Response ActiveSync command from 6.1 devices as this appears to be the cause. The code below puts the effected devices calendar into Ready Only mode until Apple release an update.

 if {[HTTP::header "User-Agent"] matches_regex {^Apple.*1002.*} } {
	 if { [HTTP::uri] contains "Cmd=MeetingResponse" } { 
		reject 
	}
 }

Please use this at your own risk.

Dan.

I'm a newb - Where do I add this code? I haven't seen our logs grow abnormally yet - but I'd like to use it just incase... I'm just not experienced enough to know where to put it. Guidance please?

Thanks in advance!
Posted By Gleep52 on 02/08/2013 10:51 AM
I'm a newb - Where do I add this code? I haven't seen our logs grow abnormally yet - but I'd like to use it just incase... I'm just not experienced enough to know where to put it. Guidance please?
 


This is iRule code for an F5 LTM virtual server. (This post has been referenced externally in several places now so people reading might not be aware this discussion is specifically referring to using iRules on F5 BIG-IP:LTM in front of Exchange).  

This is just a snippet of code as well, it needs to be encapsulated in the HTTP_REQUEST event to form a complete iRule to be added to the virtual server. Gleep52, if by chance I have misinterpreted your request and you still need assistance with forming this into a complete iRule on an LTM, please post back.


when HTTP_REQUEST  {    
	if {[HTTP::header "User-Agent"] matches_regex {^Apple.*1002.*} } {
		if { [HTTP::uri] contains "Cmd=MeetingResponse" } { 
			log 10.10.10.1 local0.info "Denied iOS 6.1 Device SNAT src=[IP::client_addr] src_port=[TCP::client_port], snat_src=[IP::local_addr] snat_src_port=[TCP::local_port], dst=[IP::server_addr] dst_port=[TCP::server_port]"
			reject 
		}
	}  
}
 


Above is the complete iRule we placed in the TMG virtual server. We see several client IP's that are looped with above 60,000 denies and it goes down from there to about 7 cilents with denies above 3,000 the rest are below 300.

You have to know where to place this iRule in terms of execution order since there are other iRules running on the Exchange single virtual.

The easiest way is to give it higher priority than existing iRules used with the Exchange virtual.
By default an iRule event has a priority of 500. The lower the better, so we give this one a priority of 100.

To do that, add this command : "priority 100" before balias's irule above. So you get this:

priority 100
when HTTP_REQUEST {
if {[HTTP::header "User-Agent"] matches_regex {^Apple.*1002.*} } {
if { [HTTP::uri] contains "Cmd=MeetingResponse" } {
log 10.10.10.1 local0.info "Denied iOS 6.1 Device SNAT src=[IP::client_addr] src_port=[TCP::client_port], snat_src=[IP::local_addr] snat_src_port=[TCP::local_port], dst=[IP::server_addr] dst_port=[TCP::server_port]"
reject
}
}
}



See this Excellent article for information about iRule Events and Event priorities: https://devcentral.f5.com/tech-tips...RfEYlFAWdk


For anyone new to F5 LTM.

Copy iRule above.

Connect to BigIP GUI. Go to "Local Traffic/IRules". Choose "Create" at far right. Enter a name for iRule. (no spaces)

Paste iRule in input box then Hit Update.

Go to "Local Traffic/Virutals", a list of virtuals appears. Locate the Exchange virtual, Click on "Edit" under Resources Column at the far right side of screen.

IRule section appears. (middle of screen), click on "Manage" far right of screen. Add the recently created iRule.

HTH.

John,

We implemented the iRule as you suggested and saw an immediate drop in the thrashing of our transaction logs. Thanks for the great write up!

Jason Ford

First of all thank you for the iRule, we will implement it in our environment as well.

But does anybody knows the User-Agent for iOS 6.1.1, because I heard that the bug is not solved in this version. Is it also starting with 1002 and only the number behind the dot is different (I think so due to minor release).

Thank you!

 

Ciao Stefan :)

Hi Stefan,

Yes this solution does block iOS 6.1.1 as most of 6.1 was between 1002.140 > 1002.144 with 6.1.1 being .145. Until Apple clearly state the Exchange Bug has been resolved we will continue to use this interim soluion.

-Dan

I registered to this group as "Jealous" because we don't have an F5 switch but maybe wish we did to be able to solve this issue...

A couple questions: Are you using SSL with ActiveSync? If you are, how is the F5 able to read the HTTP headers to reject the requests?

We've considered using Snort to shun the requests but cannot read the packets because they are encrypted with SSL.

Hi, welcome and it would be best to look up the F5 bigip LTM F5's product page because the F5s accomplish a lot of things in one package.

We have the certificate used by activesync residing on the F5 BIGIP LTM for SSL offload, so yes we are using SSL.  You can also re-encrypt connections to servers from the F5 if you so desire...

We implement this IOS 6.1 workaround via real time application layer manipulation of data as it transits the F5 BigIP LTM using a TCL based scripting language (iRules).

We also have implemented this iRule now and it seems to work fine, but the client isn't getting any notification.

Is this normal or are there any other possibilities, that the client get's informed about this issue?

 

Ciao Stefan :)

Stefan,

The first iRule mentioned will give the client the following message "The connection has been refused" however the second option only rejects "Cmd=MeetingResponse" no errors or warnings are presented to the user. I suggest informing your users that their device can no longer accept, tentatively accept, or decline a meeting requests.

Daniel

Hi,
I tried the script below, but I get no good logging in ltm.
Any sugestion to fix it?

Jan

Thu Feb 14 19:04:55 CET 2013 err f5-db tmm[7737] 01220001 TCL error: /Common/iphone_6.1 - no serverside connection established (line 1) invoked from within "IP::server_addr"
Thu Feb 14 19:04:56 CET 2013 err f5-db tmm[7737] 01220001 TCL error: /Common/iphone_6.1 - no serverside connection established (line 3) invoked from within "IP::server_addr"
Thu Feb 14 19:04:57 CET 2013 err f5-db tmm[7737] 01220001 TCL error: /Common/iphone_6.1 - no serverside connection established (line 3) invoked from within "IP::server_addr"
Thu Feb 14 19:04:57 CET 2013 err f5-db tmm[7737] 01220001 TCL error: /Common/iphone_6.1 - no serverside connection established (line 3) invoked from within "IP::server_addr"
Thu Feb 14 19:04:58 CET 2013 err f5-db tmm1[7738] 01220001 TCL error: /Common/iphone_6.1 - no serverside connection established (line 1) invoked from within "IP::server_addr"

priority 100
when HTTP_REQUEST {
if {[HTTP::header "User-Agent"] matches_regex {^Apple.*1002.*} } {
if { [HTTP::uri] contains "Cmd=MeetingResponse" } {
log local0. "Denied iOS 6.1 Device SNAT src=[IP::client_addr] src_port=[TCP::client_port], snat_src=[IP::local_addr] snat_src_port=[TCP::local_port], dst=[IP::server_addr] dst_port=[TCP::server_port]"
reject
}
}
}
A serverside connection hasn't been established in HTTP_REQUEST for the first request on a TCP connection. So you'll get a runtime error if you try to run commands to return the server IP and/or port.

Can you try this version which should be more efficient using a string comparison instead of a regex?


priority 100
when HTTP_REQUEST {
	if {[string match -nocase "apple*1002*" [HTTP::header "User-Agent"] and [HTTP::uri] contains "Cmd=MeetingResponse" } {
		log local0. "Denied iOS 6.1 Device SNAT src=[IP::client_addr] src_port=[TCP::client_port], dst=[IP::local_addr] dst_port=[TCP::local_port], virtual=[virtual name]"
		reject
		event disable all
	}
}


Aaron
Aaron,

Missing some bracket on line 3.
Any sugestion for fix?

Jan
Sorry... forgot to close the string match command. Here's an update:


priority 100
when HTTP_REQUEST {
    if {[string match -nocase "apple*1002*" [HTTP::header "User-Agent"]] and [HTTP::uri] contains "Cmd=MeetingResponse" } {
        log local0. "Denied iOS 6.1 Device SNAT src=[IP::client_addr] src_port=[TCP::client_port], dst=[IP::local_addr] dst_port=[TCP::local_port], virtual=[virtual name]"
        reject
        event disable all
    }
}


Aaron
Thank you. :-)
I will test it and see if the logging work better with your irule.

-J-
Does the meeting request in Exchange stay in tact with this iRule. So normally I respond to a meeting a meeting from my iPhone and it gets moved to deleted items. Would that be the case here or would the meeting stay in my inbox until I accepted or denied it from another client?
I add the following rule, but users are still able to accesse their mail via iphones. Am i doing something wrong?
when HTTP_REQUEST {
if {[string match -nocase "apple*1002*" [HTTP::header "User-Agent"]] and [HTTP::uri] contains "Cmd=MeetingResponse" } {
log local0. "Denied iOS 6.1 Device SNAT src=[IP::client_addr] src_port=[TCP::client_port], dst=[IP::local_addr] dst_port=[TCP::local_port], virtual=[virtual name]"
reject
event disable all
}
}
Barry,
This rule is not to restrict access to Mail but rather to specifically block access to them using the MeetingResponse Cmd within Exchange. So essentially they can't Accept or Decline meeting but they can still do all other Exchange sync functionality.

Hi all,

As IOS 6.1.2 is out, anybody who know the new version number?

Jan

Updated to allow iOS 6.1.2 (which is 1002.146). This rule will match versions 1002.1 through 1002.145:
 

if {[HTTP::header "User-Agent"] matches_regex {^Apple.*1002.([1-9]|[1-9][0-9]|1[0-3][0-9]|14[0-5])$} } { if { [HTTP::uri] contains "Cmd=MeetingResponse" } { reject } } 

 

Hi Mike

appreciate the code share, we will be applying this shortly.


-Daniel

Here's what we have right now, seems to be working for the moment:

priority 100
when HTTP_REQUEST {

if {[HTTP::header "User-Agent"] matches_regex {^Apple.*1002.146} } {
if { [HTTP::uri] contains "Cmd=MeetingResponse" } {
pool
}
}
elseif {[HTTP::header "User-Agent"] matches_regex {^Apple.*1002.*} } {
if { [HTTP::uri] contains "Cmd=MeetingResponse" } {
reject
}
}
}

 

 

I like Goat's iRule better, using it now, works great.

Thanks Goat!
Anybody who can review this irule and see any problem, before I try this live?

priority 100
when HTTP_REQUEST {
if {[HTTP::header "User-Agent"] matches_regex {^Apple.*1002.([Z1-9]|[Z1-9][Z0-9]|1[Z0-3][Z0-9]|14[Z0-5])$} } { if { [HTTP::uri] contains "Cmd=MeetingResponse" } { reject } }
log local0. "Denied iOS 6.1 Device SNAT src=[IP::client_addr] src_port=[TCP::client_port], dst=[IP::local_addr] dst_port=[TCP::local_port], virtual=[virtual name]"
event disable all

}

Jan, from a functionality perspective;

1) The log and event disable all commands are outside the second if statement, it will run these every time even if there is no match, they need to be moved to after the reject and before the } }

Regarding performance;


1) Would it not be better to check for "Cmd=MeetingResponse" first to save running the 'expensive' regex every time the rule is fired
2) Do you really need to log that level of information?

Hi Steve,

I can skip the event disable all.
No I would like to check the Apple version first and then MeetingResponse, but you right regex maybye not the best tool for match.
The log is good to have for troubleshooting, but the level could be less.

This is what I use right now, but I need to allow 1002.146 and block between 1002.140 > 1002.145
Any sugestion to solve it?

priority 100
when HTTP_REQUEST {
if {[string match -nocase "apple*1002*" [HTTP::header "User-Agent"]] and [HTTP::uri] contains "Cmd=MeetingResponse" } {
log local0. "Denied iOS 6.1.x src=[IP::client_addr] src_port=[TCP::client_port], dst=[IP::local_addr] dst_port=[TCP::local_port], virtual=[virtual name]"
reject
event disable all
}
}

Jan
This should do it;

when HTTP_REQUEST {
 switch -glob [string tolower [HTTP::header User-Agent]] {
  "*1002.140*" -
  "*1002.141*" -
  "*1002.142*" -
  "*1002.143*" -
  "*1002.144*" -
  "*1002.145*" {
   if { [HTTP::uri] contains "Cmd=MeetingResponse" } {
    reject
    log local0. "Denied iOS 6.1 Device SNAT src=[IP::client_addr] src_port=[TCP::client_port], dst=[IP::local_addr] dst_port=[TCP::local_port], virtual=[virtual name]"
   }
  }
 }
}
Actually, so should this much more efficient version;

when HTTP_REQUEST {
 switch -glob [string tolower [HTTP::header User-Agent]] {
  "*1002.14[0-5]*" {
   if { [HTTP::uri] contains "Cmd=MeetingResponse" } {
    reject
    log local0. "Denied iOS 6.1 Device SNAT src=[IP::client_addr] src_port=[TCP::client_port], dst=[IP::local_addr] dst_port=[TCP::local_port], virtual=[virtual name]"
   }
  }
 }
}
Posted By Goat on 02/19/2013 01:47 PM

Updated to allow iOS 6.1.2 (which is 1002.146). This rule will match versions 1002.1 through 1002.145:



if {[HTTP::header "User-Agent"] matches_regex {^Apple.*1002.([Z1-9]|[Z1-9][Z0-9]|1[Z0-3][Z0-9]|14[Z0-5])$} } { if { [HTTP::uri] contains "Cmd=MeetingResponse" } { reject } } 

 



Can you explain the requirement of using the capital Z in your syntax, which is preceeding either a 1 or 0?  

Just showing off my (lack of) RegEx skills.  surprise  I've edited my post with the correction.  If you are already using the code I posted early, it DOES WORK, but you'll probably want to remove the unnecessary 'Z's going forward.

Thanks for pointing out the mistake, barakaspeed!

I implemented What Lies Beneath's iRule last night and it works great. Since my iRules-fu is nowhere as good as yours, I am wondering if it is possible to pull out the username and add that to the logging portion of this rule. I see a ton of hits when these rules block a request, but no real good way to tie it back to a user.

 

Thanks for posting this very helpful iRule

Do you know where the username is? Is it in a header or the payload data?

Pretty certain it is in the payload, I am investigating to see if I can confirm.

If you find it we can use something like this (untested);

when HTTP_REQUEST {
set collectdata 0
 switch -glob [string tolower [HTTP::header User-Agent]] {
  "*1002.14[0-5]*" {
   if { [HTTP::uri] contains "Cmd=MeetingResponse" } {
    set collectdata 1
    HTTP::collect 0 0
   }
  }
 }
}

when HTTP_REQUEST_DATA {
 if { $collectdata = 1 } {
  scan [HTTP::payload] {%*s login %s} username
  reject
  log local0. "Denied iOS 6.1 Device SNAT src=[IP::client_addr] , virtual=[virtual name], user=$username"
  HTTP::release
  return
 }
}

We used the switch-case method and it's working fine.

The username is visible in our environment in the URI, this is our log-statement:

log local0. "Denied iOS 6.1 Device, User-Agent: [HTTP::header "User-Agent"], URI: [HTTP::uri]"

 

Ciao Stefan :)

We took a shot that our usernames were exposed in the URI and they are. We simply added that to the log command and now we are set.

 

Thanks everyone, this was very helpful.

Your answer: