Forum Discussion

Thornid's avatar
Thornid
Icon for Nimbostratus rankNimbostratus
Jul 01, 2019

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.

9 Replies

  • 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.