Forum Discussion
iRule config to Rewrite SSL Header for Transactions
We need to pull three values out of the Client SSL and put them in the Server SSL. Currently we tried using a rule that creates a Session Table to store these. Since this is a API and not a web page we are having timeout issues. Any suggestions on rewriting this would help.
This is part of what we are using.
when CLIENTSSL_CLIENTCERT {
Check if client presented at least one cert if {[SSL::cert count] > 0}{
Insert the following fields in the session table with a timeout of 7200 seconds:
Do the processing now as opposed to in HTTP_REQUEST as there
can be many HTTP requests using the same SSL session ID
Index - item
1 - serial number of the cert
2 - issuer of the cert
3 - subject of the cert
session add ssl [SSL::sessionid] [list \
[SSL::verify_result] \
[X509::serial_number [SSL::cert 0]] \
[X509::issuer [SSL::cert 0]] \
[X509::subject [SSL::cert 0]] \
] 7200
log local0. "[IP::client_addr]:[TCP::client_port]: Added session data for cert. Status:\
[X509::verify_cert_error_string [lindex [session lookup ssl [SSL::sessionid]] 0]] with key [SSL::sessionid]"
} }
12 Replies
- Kevin_Stewart
Employee
Can you clarify "and put them in the Server SSL"? The session table is an in-memory structure on the BIG-IP to store session-related information (persistence info, random data, etc.). This information does not leave the table. Are you attempting to insert information into the actual SSL session going to the server? If so, can you elaborate on your intentions?
- PicassoMendez
Nimbostratus
What we are trying to do is rewrite the header from the Client to the Server with three values. Those are listed in the script screen shot. I am a novice in writing irules so are using one that works for a web page. Would the full script of the irule help?
- Kevin_Stewart
Employee
Would the full script of the irule help?
Probably. I just want to clarify one thing though. You're using the term "SSL header", which is confusing. Do you mean an HTTP header inside an SSL session, or an SSL "header" inside the SSL handshake?
- PicassoMendez
Nimbostratus
You are correct in that it is a HTTP header inside an SSL session
- Kevin_Stewart
Employee
Ahh, well then the server SSL doesn't matter. Actually, and I believe this behavior changed not too long ago, the SSL::cert information should persist across requests, so you should simply be able to do something like this:
when HTTP_REQUEST { HTTP::header insert CERTDATA "[SSL::verify_result] - [X509::serial_number [SSL::cert 0]] - [X509::issuer [SSL::cert 0]] - [X509::subject [SSL::cert 0]]" } - PicassoMendez
Nimbostratus
Will this put the info in the header that is sent to the pool?
- PicassoMendez
Nimbostratus
That didn't come out good. Here is the full test of the irule. Which lines would I remove?
URI Modify with Client Cert Header insertwhen CLIENT_ACCEPTED { set default_pool [LB::server pool] }
when CLIENTSSL_CLIENTCERT {
Check if client presented at least one cert if {[SSL::cert count] > 0}{
Insert the following fields in the session table with a timeout of 7200 seconds: Do the processing now as opposed to in HTTP_REQUEST as there can be many HTTP requests using the same SSL session ID Index - item 1 - serial number of the cert 2 - issuer of the cert 3 - subject of the cert session add ssl [SSL::sessionid] [list \ [SSL::verify_result] \ [X509::serial_number [SSL::cert 0]] \ [X509::issuer [SSL::cert 0]] \ [X509::subject [SSL::cert 0]] \ ] 7200 log local0. "[IP::client_addr]:[TCP::client_port]: Added session data for cert. Status:\ [X509::verify_cert_error_string [lindex [session lookup ssl [SSL::sessionid]] 0]] with key [SSL::sessionid]"} }
when HTTP_REQUEST { if { [HTTP::uri] starts_with "/markets/VirtualTransactionProducingService" } { discard } elseif { [HTTP::uri] starts_with "/settlements/BilateralScheduleService/v1/BilateralScheduleService" } { HTTP::uri "/BilateralSchedulesCore/BilateralSchedulesService/BilateralPortImpl[string range [HTTP::uri] 65 end]" pool POOL-ITE-DMZ-8080-api.itespp.org-Bilateral } elseif { [HTTP::uri] starts_with "/settlements/MeterDataService/v1/MeterDataService" } { HTTP::uri "/MeterDataCore/MeterDataService/MeterDataPortImpl[string range [HTTP::uri] 49 end]" pool POOL-ITE-DMZ-8080-api.itespp.org-MeterData } elseif { [HTTP::uri] starts_with "/settlements/SettlementReportService/v1/SettlementReportService" } { HTTP::uri "/webservices/SettlementReportsService/SettlementReportsPortImpl[string range [HTTP::uri] 63 end]" pool POOL-ITE-DMZ-8080-api.itespp.org-Settlement } elseif { [HTTP::uri] starts_with "/settlements/SettlementReportService/v1/SettlementReportInternalService" } { HTTP::uri "/webservices/SettlementReportsService/SettlementReportsInternalPortImpl[string range [HTTP::uri] 70 end]" pool POOL-ITE-DMZ-8080-api.itespp.org-Settlement } elseif { [HTTP::uri] starts_with "/notifications/NotificationService/v1/NotificationSyncService" } { HTTP::uri "/NotificationEjb/NotificationSyncService/NotificationSyncService[string range [HTTP::uri] 61 end]" pool POOL-ITE-DMZ-8443-api.itespp.org-Notification } elseif { [HTTP::uri] starts_with "/markets/MarketStatusProducingService" } { HTTP::uri "/extif[string range [HTTP::uri] 8 end]" pool POOL-ITE-DMZ-8443-api.itespp.org-extif } elseif { [HTTP::uri] starts_with "/markets/MarketClearedTransactionsProducingService" } { HTTP::uri "/extif[string range [HTTP::uri] 8 end]" pool POOL-ITE-DMZ-8443-api.itespp.org-extif } elseif { [HTTP::uri] starts_with "/markets/TotalTLRReliefConsumingService" } { HTTP::uri "/extif[string range [HTTP::uri] 8 end]" pool POOL-ITE-DMZ-8443-api.itespp.org-extif } elseif { [HTTP::uri] starts_with "/markets/ReserveEventConsumingService" } { HTTP::uri "/extif[string range [HTTP::uri] 8 end]" pool POOL-ITE-DMZ-8443-api.itespp.org-extif } elseif { [HTTP::uri] starts_with "/markets/ReserveObligationConsumingService" } { HTTP::uri "/extif[string range [HTTP::uri] 8 end]" pool POOL-ITE-DMZ-8443-api.itespp.org-extif } elseif { [HTTP::uri] starts_with "/markets/CurtailedWindResourcesProducingService" } { HTTP::uri "/extif[string range [HTTP::uri] 8 end]" pool POOL-ITE-DMZ-8443-api.itespp.org-extif } elseif { [HTTP::uri] starts_with "/markets/MarketTransactionConsumingService" } { pool POOL-ITE-DMZ-8419-api.itespp.org } elseif { [HTTP::uri] starts_with "/markets/IntervalNSIConsumingService" } { pool POOL-ITE-DMZ-8420-api.itespp.org } elseif { [HTTP::uri] starts_with "/markets/InterfaceNSIConsumingService" } { pool POOL-ITE-DMZ-8424-api.itespp.org } elseif { [HTTP::uri] starts_with "/markets/HourlyInadvertentConsumingService" } { pool POOL-ITE-DMZ-8425-api.itespp.org } elseif { [HTTP::uri] starts_with "/markets/WindResourceForecastConsumingService" } { pool POOL-ITE-DMZ-8427-api.itespp.org } elseif { [HTTP::uri] starts_with "/markets/TielineMeterProducingService" } { pool POOL-ITE-DMZ-8428-api.itespp.org } elseif { [HTTP::uri] starts_with "/markets/WindResourceTelemetryProducingService" } { pool POOL-ITE-DMZ-8429-api.itespp.org } elseif { [HTTP::uri] starts_with "/markets" } { pool POOL-ITE-DMZ-8443-api.itespp.org }
Remove x-headers from the request to remove injection attacks foreach header_name [HTTP::header names] {
if {[string match -nocase x-* $header_name]}{ HTTP::header remove $header_name }}
Add the address of the original client to the headers HTTP::header insert X-Forwarded-For [IP::remote_addr]
Check if SSL session ID is in the cache (SSL::sessionid returns 64 zeroes if it's not in v9 and a null string in v10) if {[SSL::sessionid] ne "0000000000000000000000000000000000000000000000000000000000000000" && [SSL::sessionid] ne ""}{
Get the session table entry (a TCL list) for this session ID set session_data [session lookup ssl [SSL::sessionid]] Check if the first element of the session table entry for this session ID is 0 (status for successful cert validation) if {[lindex $session_data 0] == 0}{ log local0. "[IP::client_addr]:[TCP::client_port]: Valid cert per session table entry. Inserting cert details in HTTP headers." Remove colons and dashes in the certificate serial number regsub -all : [lindex $session_data 1] "" CERT_SerialNumber Insert cert details in the HTTP headers HTTP::header insert X-SPP-CERT-SerialNumber [ string toupper $CERT_SerialNumber ] HTTP::header insert X-SPP-CERT-IssuerDN [lindex $session_data 2] HTTP::header insert X-SPP-CERT-SubjectDN [lindex $session_data 3] Exit this event in this rule return }} If we're still in this rule, cert wasn't valid so send HTTP 302 redirect to an error page HTTP::respond 302 Location "http://[HTTP::host]/cert_error.html"
log local0. "[IP::client_addr]:[TCP::client_port]: No or invalid cert from client." }
- Kevin_Stewart
Employee
It's an HTTP header insertion, so it'd go in your HTTP_REQUEST event. You probably don't need to store the cert data in a session table.
- Kevin_Stewart
Employee
Apologies, but I'm not really following your iRule. I can say this though, you could probably modify the last part of the HTTP_REQUEST event to do something like this:
set session_data [session lookup ssl [SSL::sessionid]] if { $session_data ne "" } { HTTP::header insert X-SSP-CERT-SerialNumber [lindex $session_data 1] HTTP::header insert X-SSP-CERT-IssuerDN [lindex $session_data 2] HTTP::header insert X-SSP-CERT-SubjectDN [lindex $session_data 3] } - PicassoMendez
Nimbostratus
Not exactly sure about that last statement. Would I do this instead of the other command or in addition to?
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)Recent Discussions
Related Content
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com