TCP Option 28 X-Forwarded-For Header
Using Akamai for DDOS mitigation and the requests sent to us show Akamai IP instead of the Client IP. I have enabled TCP Option 28 and trying to insert the Client IP into X-Forwarded-For header. I had to add this configuration into an existing iRule and getting Err_Connection_Reset. Any assistance on what I'm doing wrong would be greatly appreciated.
The entire iRule is below and I have bolded the new TCP Option 28 config. The rest of the iRule was working properly before I added this.
when CLIENT_ACCEPTED {
set proto 0
if { [PROFILE::exists clientssl] } {
set default_tls_pool [LB::server pool]
set detect_handshake 1
SSL::disable
TCP::collect
} else {
log local0. "This iRule is applied to a VS that has no clientssl profile."
set detect_handshake 0
}
set opt28 [TCP::option get 28]
if { [string length $opt28] == 5 } {
binary scan $opt28 c ver
if { $ver != 1 } {
log local0. "Unsupported Akamai version: $ver"
} else {
set optaddr [IP::addr parse -ipv4 $opt28 1]
}
}
}
when CLIENTSSL_CLIENTHELLO {
set proto 1
}
when HTTP_REQUEST {
if {$proto} {
if { [info exists optaddr] } {
HTTP::header insert X-Forwarded-Proto https
HTTP::header insert X-Forwarded-For $optaddr
} else {
HTTP::header insert X-Forwarded-Proto https
}
} else {
if { [info exists optaddr] } {
HTTP::header insert X-Forwarded-Proto http
HTTP::header insert X-Forwarded-For $optaddr
} else {
HTTP::header insert X-Forwarded-Proto http
}
}
}
when CLIENT_DATA {
if { ($detect_handshake) } {
binary scan [TCP::payload] cSS tls_xacttype tls_version tls_recordlen
switch $tls_version {
"769" -
"770" -
"771" {
if { ($tls_xacttype == 22) } {
binary scan [TCP::payload] @5c tls_action
if { not (($tls_action == 1) && ([TCP::payload length] > $tls_recordlen)) } {
set detect_handshake 0
}
}
}
default {
set detect_handshake 0
}
}
if { ($detect_handshake) } {
set record_offset 43
binary scan [TCP::payload] @${record_offset}c tls_sessidlen
set record_offset [expr {$record_offset + 1 + $tls_sessidlen}]
binary scan [TCP::payload] @${record_offset}S tls_ciphlen
set record_offset [expr {$record_offset + 2 + $tls_ciphlen}]
binary scan [TCP::payload] @${record_offset}c tls_complen
set record_offset [expr {$record_offset + 1 + $tls_complen}]
if { ([TCP::payload length] >= $record_offset) } {
binary scan [TCP::payload] @${record_offset}S tls_extenlen
set record_offset [expr {$record_offset + 2}]
binary scan [TCP::payload] @${record_offset}a* tls_extensions
for { set x 0 } { $x < $tls_extenlen } { incr x 4 } {
set start [expr {$x}]
binary scan $tls_extensions @${start}SS etype elen
if { ($etype == "00") } {
set grabstart [expr {$start + 9}]
set grabend [expr {$elen - 5}]
binary scan $tls_extensions @${grabstart}A${grabend} tls_servername
set start [expr {$start + $elen}]
} else {
set start [expr {$start + $elen}]
}
set x $start
}
if { ([info exists tls_servername] ) } {
set ssl_profile [class match -value [string tolower $tls_servername] ends_with tls_servername]
set tls_pool [class match -value [string tolower $tls_servername] ends_with tls_servername_pool]
if { $ssl_profile == "" } {
SSL::enable
} else {
set ssl_profile_enable "SSL::profile $ssl_profile"
catch { eval $ssl_profile_enable }
if { not ($tls_pool == "") } {
pool $tls_pool
} else {
pool $default_tls_pool
}
SSL::enable
}
} else {
SSL::enable
}
} else {
SSL::enable
}
set detect_handshake 0
TCP::release
} else {
set detect_handshake 0
SSL::enable
TCP::release
}
}
}
when CLIENT_DATA {
set opt28 [TCP::option get 28]
if { [string length $opt28] == 4 } {
binary scan $opt28 H8 addr
scan $addr "%2x%2x%2x%2x" ip1 ip2 ip3 ip4
set optaddr "$ip1.$ip2.$ip3.$ip4"
log local0. "optaddr is $optaddr"
log local0. "ip addr parse result is [IP::addr parse -ipv4 $opt28]"
}
}