on 17-Mar-2015 14:31
Problem this snippet solves:
This iRule adds captcha verification to a virtual server.
The implementation is described in George Watkins' article: Google reCAPTCHA Verification With Sideband Connections
This iRule can be added to a virtual server. Each initial request will receive a captcha challenge prior to being allowed access to protected resources.
Code :
when RULE_INIT { # set DNS server address to resolve www.google.com set static::dns_server 10.0.0.254 # set public and private reCAPTCHA keys (obtain from www.recaptcha.com) set static::recaptcha_public_key "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" set static::recaptcha_private_key "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # set name of table to track reCAPTCHA approvals set static::recaptcha_approval_table "recaptcha_approvals" # set name of table to track last requested URL set static::recaptcha_redirect_table "recaptcha_redirects" # timeout and/or lifetime for reCAPTCHA approval set static::recaptcha_approval_timeout 3600 set static::recaptcha_approval_lifetime 3600 # log level, 0 = silent, 1 = log client interaction, 2 = log all interaction with client and Google set static::logging 1 # begin - HTML for reCAPTCHA form page set static::recaptcha_challenge_form {Hold up there! } # end - HTML for reCAPTCHA form page } when CLIENT_ACCEPTED { set session_identifier "[IP::client_addr]:[TCP::client_port]/[IP::local_addr]:[TCP::local_port]" } when HTTP_REQUEST { if { [HTTP::path] equals "/verify_recaptcha" } { set recaptcha_challenge_field [URI::query [HTTP::uri] "recaptcha_challenge_field"] set recaptcha_response_field [URI::query [HTTP::uri] "recaptcha_response_field"] if { $static::logging >= 1 } { log local0. "Session \"$session_identifier\": user responded with \"$recaptcha_response_field\"" } # assemble body of reCAPTCHA verification POST set recaptcha_post_data "privatekey=$static::recaptcha_private_key&" append recaptcha_post_data "remoteip=[IP::remote_addr]&" append recaptcha_post_data "challenge=$recaptcha_challenge_field&" append recaptcha_post_data "response=$recaptcha_response_field" # calculate Content-length header value set recaptcha_post_content_length [string length $recaptcha_post_data] # assemble reCAPTCHA verification POST request set recaptcha_verify_request "POST /recaptcha/api/verify HTTP/1.1\r\n" append recaptcha_verify_request "Host: www.google.com\r\n" append recaptcha_verify_request "Accept: */*\r\n" append recaptcha_verify_request "Content-length: $recaptcha_post_content_length\r\n" append recaptcha_verify_request "Content-type: application/x-www-form-urlencoded\r\n\r\n" append recaptcha_verify_request "$recaptcha_post_data" # resolve Google's IP address and stuff it into a variable set google_ip [lindex [RESOLV::lookup @$static::dns_server -a "www.google.com"] 0] # establish connection to Google set conn [connect -timeout 1000 -idle 30 $google_ip:80] # send reCATPCHA verification request to Google send -timeout 1000 -status send_status $conn $recaptcha_verify_request if { $static::logging >= 2 } { log local0. "Session \"$session_identifier\": sending reCAPTCHA verification to Google: \"$recaptcha_verify_request\"" } # receive reCAPTCHA verification response from Google set recaptcha_verify_response [recv -timeout 1000 -status recv_info $conn] if { $static::logging >= 2 } { log local0. "Session \"$session_identifier\": received verification response from Google: \"$recaptcha_verify_reponse\"" } close $conn # process reCAPTCHA verification response and remove user session from trigger table if successful if { $recaptcha_verify_response contains "success" } { set redirect_url [table lookup -subtable $static::recaptcha_redirect_table -notouch $session_identifier] table add -subtable $static::recaptcha_approval_table $session_identifier 1 \ $static::recaptcha_approval_timeout $static::recaptcha_approval_lifetime if { $static::logging >= 1 } { log local0. "Session \"$session_identifier\": passed captcha and was added to approval table" log local0. "Session \"$session_identifier\": redirecting to \"$redirect_url\"" } HTTP::redirect $redirect_url } else { HTTP::respond 200 content $static::recaptcha_challenge_form if { $static::logging >= 1 } { log local0. "Session \"$session_identifier\": failed captcha" } } } elseif { [table lookup -subtable $static::recaptcha_approval_table $session_identifier] eq ""} { table add -subtable $static::recaptcha_redirect_table $session_identifier "http://[HTTP::host][HTTP::uri]" 3600 3600 HTTP::respond 200 content $static::recaptcha_challenge_form } }Hold up there!
We want to make sure that you're a human before you can use this virtual server!