Restrict Source IPs iRule

Hi all

Forgive what may be such an easy iRule question but unfortunately my experience with them is rather limited and time is of the essence. We have an iRule which looks to be doing something with the client certificate as you can see:

when CLIENTSSL_CLIENTCERT priority 500 {
	set cnAllowClass "[string range [virtual name] 0 end-2]cn_allow_class"
	set clientCertRequiredClass "[string range [virtual name] 0 end-2]client_cert_required_class"
	set clientCertHeaderName "ssl_client_cert"
	set clientIP [IP::client_addr]
	if {[SSL::cert count] eq 0} {
		reject
		return
	} else {
		set subjectDN [string tolower [X509::subject [SSL::cert 0]]]
		if {[class match $subjectDN contains $clientCertRequiredClass] ne 0} {
			set clientCertHeaderValue [b64encode [SSL::cert 0]]
			set flgInsertClientCertHeader 1
		}
	}
	set cnExists [class match $subjectDN contains $cnAllowClass]
	if {$cnExists ne 0} {
	} else {
		reject
	}
}

…what we need to do is add something in before this code that will say, in plain English:

“if the source IP address is a.b.c.d, then use SSL profile abcd. If not, then use SSL profile efgh.”

Any ideas on how we can achieve this?

Thank you.

Hi

You need some logic within the CLIENT_ACCEPTED Event for this. Something like this for a single IP…this will look for a connection from 10.10.10.10 and apply a different SSL profile. All other connections will used the default config of the VIP

when CLIENT_ACCEPTED {     
  if { [IP::addr [IP::client_addr] equals 10.10.10.10] } {
     SSL::profile new_clientssl
 }
}

You can expand out for look for a subnet

when CLIENT_ACCEPTED {     
  if { [IP::addr [IP::client_addr] equals 10.10.10.0/24] } {
     SSL::profile new_clientssl
 }
}

or use a DataGroup if you want to…

when CLIENT_ACCEPTED {     
    if { [class match [IP::client_addr] equals source_ip] } {  
		SSL::profile new_clientssl
	}
}

Thank you iaine

That was something that did come across my mind but then I realised that I framed the question incorrectly, apologies.

The logic should actually read:

“if the source IP address is a.b.c.d, then use SSL profile abcd, then stop processing, i.e. do not process other logic in the iRule”

Essentially, there are some clients that we need to come into this VS but not be subject to the iRule logic (client cert, checks etc.) So need a way to allow them to come in and use an SSL profile that does not have Client Authentication enabled, then stop. All other clients just continue as normal using the default SSL profile (with client auth applied).

Thanks

Hi

To stop processing the iRule further, you can either use Event disable command or you can use a variable to stop specific events or part of code from running depending on requirements. Such as…

when CLIENT_ACCEPTED {     
  if { [IP::addr [IP::client_addr] equals 10.10.10.0/24] } {
     SSL::profile new_clientssl
	set sourceip 1 
 }
}
 
when CLIENTSSL_CLIENTCERT {
	if {[info exists sourceip]}{
		return}

	}

this uses return to stop this particular event

Brill, thanks iaine

Out of curiosity, setting the variable ‘sourceip 1’ - what does ‘1’ in this instance mean or refer to?

hi - it’s just an arbitrary value so that the attribute contains something when info exists queries it.

Excellent, that makes sense. I shall be giving this a whirl a bit later today and will report back.

Thank you iaine.

Hi iaine

Hasn’t quite worked as expected. I added the new code snippet as follows:

when CLIENT_ACCEPTED {     
  if { [IP::addr [IP::client_addr] equals 1.2.3.4/32] } {
    SSL::profile new-ssl-profile
	set sourceip 1 
 }
}
 
when CLIENTSSL_CLIENTCERT priority 500 {
    if {[info exists sourceip] }{
		return}
	set cnAllowClass "[string range [virtual name] 0 end-2]cn_allow_class"
	set clientCertRequiredClass "[string range [virtual name] 0 end-2]client_cert_required_class"
	set clientCertHeaderName "ssl_client_cert"
	set clientIP [IP::client_addr]
	if {[SSL::cert count] eq 0} {
		reject
		return
	} else {
		set subjectDN [string tolower [X509::subject [SSL::cert 0]]]
		if {[class match $subjectDN contains $clientCertRequiredClass] ne 0} {
			set clientCertHeaderValue [b64encode [SSL::cert 0]]
			set flgInsertClientCertHeader 1
		}
	}
	set cnExists [class match $subjectDN contains $cnAllowClass]
	if {$cnExists ne 0} {
	} else {
		reject
	}
}

…yet when we debug this we see that the iRule does not stop at the CLIENTSSL_CLIENTCERT event and we get this log:

TCL error: /Common/test-irule <HTTP_REQUEST> - can't read "clientCertHeaderName": no such variable     while executing "HTTP::header exists $clientCertHeaderName"

Any ideas?

Hi

Have you confirmed that the CLIENT_ACCEPTED code is firing. Put a log statement in after the SSL profile line just to confirm that this is working

when CLIENT_ACCEPTED {     
  if { [IP::addr [IP::client_addr] equals 1.2.3.4/32] } {
    SSL::profile new-ssl-profile
	set sourceip 1 
        log local0. " Source IP Config is working for [IP::client_addr]"

Hi iaine

Sorry for the delay. We actually got it working in the end. There was actually more code past the CLIENTSSL_CLIENTCERT event - HTTP REQUEST, we just added the if info exists return statement in there and voila, it worked.

Thank you for your effort and patience with this one.