Forum Discussion

Jim_Sadleir's avatar
Jim_Sadleir
Icon for Nimbostratus rankNimbostratus
Jan 09, 2023

iRule 'HTTP::respond 403' assistance.

Hello DevCentral Technical Forum,
I would greatly appreciate assistance getting an iRule working properly.

Our service providers US based support used to be exemplary in assisting us with our iRule requirements. Unfortunately since the 21Jul21 "restructuring" of support to their offshore support colleagues, iRule support prowess is not as robust as their US support colleagues previously provided.


Web Services requests come from outside public IP addresses and internal web server private IP addresses and are sent to TCP port 8080 which is Tomcat based.

We realized there was a certain path to one of the Tomcat based Web Services that should only be allowed from inside our environment and we want to return HTTP 403 to the client if the path came from an outside public IP address.

I found the below post for guidance in implementing the 'HTTP::respond 403' syntax but it did not work for our configuration.
https://community.f5.com/t5/technical-forum/irule-to-deny-not-working-as-expected-http-403-response-not/td-p/216428

When we flip to version 6 of the iRule (VS-1.1.1.1-SSL-8080-WEB-SERVICES-V6) which contains the additional 'HTTP::respond 403' section and I perform an external Web Browser client test containing the path that should be blocked, I get ERR_CONNECTION_RESET in the browser instead of the desired HTTP 403 response with the supporting text "You do not have authorization to view this page. Access Denied.".

As the initial version of the iRule (-V5) where I initially added the 'HTTP::respond 403' section failed with ERR_CONNECTION_RESET, as an experiment, I put it in its own 'when HTTP_REQUEST' section (-V6) which did not work either.

I only have guest GUI access to our service providers F5 BIG-IP iSeries Local Traffic Manager i2600 (Version 14.1.5.1) and it is difficult to obtain logging now as compared to the US support days. Via the Guest GUI access, I see the failures counter incrementing for the iRule statistics Event Type HTTP_REQUEST sections when I execute the browser tests.

Any additional opportunities for optimization of the iRule are greatly appreciated.


The relevant portion of the configuration with IP addresses, etc. sanitized:

ltm data-group internal /Common/CLASS-PRIVATE-IPS {
records {
10.0.0.0/8 { }
172.16.0.0/12 { }
192.168.0.0/16 { }
}
type ip
}

ltm virtual /Common/VS-1.1.1.1-SSL-8080-WEB-SERVICES {
destination /Common/192.168.2.6:8080
fw-enforced-policy /Common/ALLOW-8080
ip-protocol tcp
last-modified-time 2022-12-31:23:59:59
mask 255.255.255.255
pool /Common/POOL-1.1.1.1-TOMCAT-8080-WEB-SERVICES
profiles {
/Common/HTTP_Basic { }
/Common/tcp { }
/Common/wildcard.sample.com {
context clientside
}
}
rules {
/Common/VS-1.1.1.1-SSL-8080-WEB-SERVICES-V6
}
source 0.0.0.0/0
translate-address enabled
translate-port enabled
}


ltm rule VS-1.1.1.1-SSL-8080-WEB-SERVICES-V6 {
when CLIENT_ACCEPTED {
# If the connection originated from a web server listed in CLASS_SNAT_WEB_INTERNAL_ADDRESS internal LTM data-group,
# SNAT the source IP address to the VS destination IP address SNAT pool.
if { [ class match [IP::remote_addr] equals CLASS_SNAT_WEB_INTERNAL_ADDRESS]} {
snatpool SNAT-192.168.2.6
}
}
when HTTP_REQUEST {
# Read URI and convert to lower case to check for the portion in the path that we want to block public IP addresses from accessing
# but allow internal private IP addresses access. Respond to a public IP address with HTTP 403.
if { [string tolower [HTTP::uri]] contains "/path_to_block_from_outside/" and not [class match [IP::client_addr] equals CLASS-PRIVATE-IPS] } {
HTTP::respond 403 content "You do not have authorization to view this page. Access Denied." noserver Content-Type text/html Connection Close Cache-Control no-cache
}
}
when HTTP_REQUEST priority 850 {
# Read host and convert to lower case.
set HOST [string tolower [HTTP::host]]
# Select appropriate pool for a directed host request for testing that a specific web servers Tomcat is truly in good health.
switch -- $HOST {
web1.sample.com { pool POOL-192.168.1.1.1-TOMCAT-8080-WEB-SERVICES-WEB1 }
web2.sample.com { pool POOL-192.168.1.1.2-TOMCAT-8080-WEB-SERVICES-WEB2 }
web3.sample.com { pool POOL-192.168.1.1.3-TOMCAT-8080-WEB-SERVICES-WEB3 }
}
# Read URI and convert to lower case to check for the portion in the path that indicates this Web Service has to be sent to IIS.
if { [string tolower [HTTP::uri]] contains "/path_that_has_to_be_sent_to_iis/" and [active_members POOL-1.1.1.1-IIS-80-WEB-SERVICES] != 0 } {
pool POOL-1.1.1.1-IIS-80-WEB-SERVICES
} else {
pool POOL-1.1.1.1-IIS-80-WEB-SERVICES-SORRY
}
# If the request was not sent to IIS in the above check, it must be destined for the Virtual Servers default Tomcat pool
# so check to ensure all members in the Tomcat pool are available. If not, send to the Tomcat sorry server pool.
if { [active_members POOL-1.1.1.1-TOMCAT-8080-WEB-SERVICES] != 0} {
pool POOL-1.1.1.1-TOMCAT-8080-WEB-SERVICES
} else {
pool POOL-1.1.1.1-TOMCAT-8080-WEB-SERVICES-SORRY
}
}
}

  • Jim_Sadleir I believe you need the following to be swapped out for the appropriate two lines the difference is the () being added in the appropriate locations.

    if { (([string tolower [HTTP::uri]] contains "/path_to_block_from_outside/") and not ([class match [IP::client_addr] equals CLASS-PRIVATE-IPS])) } {
    
    if { (([string tolower [HTTP::uri]] contains "/path_that_has_to_be_sent_to_iis/") and ([active_members POOL-1.1.1.1-IIS-80-WEB-SERVICES] != 0)) } {

     

    • Leslie_Hubertus's avatar
      Leslie_Hubertus
      Ret. Employee

      Jim_Sadleir did Paulius's suggestion work for you? If yes, can you please hit the Accept as Solution button, so future users with the same issue can easily find the answer they need? 

      And if not, it lets the community know that you still need help.