sideband
3 TopicsEnhancing the F5 DoD Banner with EU CAPTCHA (Myra) & Sideband Validation
Features & Security Hardening (v1.3) Besides the frontend EU CAPTCHA integration, this iRule introduces several security hardening measures (P3–P9): Strict POST Enforcement: Banner acceptance is strictly limited to POST requests. Content-Security-Policy (CSP): Implements restrictive HTTP headers tailored to safely allow the CAPTCHA's verify.js script to execute. Overview and Benefits of Myra EU CAPTCHA Myra EU CAPTCHA is a bot protection solution developed in Germany. It is positioned as a sovereign, European, and 100% GDPR-compliant alternative to traditional American providers (such as Google reCAPTCHA or Cloudflare Turnstile, which are subject to the CLOUD Act). Key Features: Seamless User Experience (Zero-Click): Verification is performed automatically in the background using cryptographic calculations. The user does not need to take any action (no visual puzzles to solve, no traffic lights to identify). The system is therefore completely accessible and barrier-free. Privacy by Design: The solution operates entirely without cookies and does not use any persistent storage in the browser (meaning you do not need to add a cookie consent banner). Furthermore, no personal data is stored, and any potentially identifying metadata is anonymized using a hashing system. Security and Sovereignty: Built on Myra Security technology, the solution relies on the analysis of over 100 billion daily CDN signals. Customers benefit from a certified sovereign technology (ISO 27001, BSI C5, PCI DSS) and can mandate that data processing takes place exclusively in data centers located in Germany or within the European Union. https://www.eu-captcha.eu/ https://docs.eu-captcha.eu/integration/frontend/html-integration/ Implementation Steps 1. Configure the Internal Sideband Virtual Server The iRule requires an internal Virtual Server to route API traffic to Myra. Create a file named eucaptcha-sideband-vs.conf in /var/tmp/ on your BIG-IP with the following content: ltm node /Common/node-api.eu-captcha.eu { fqdn { autopopulate enabled interval ttl name api.eu-captcha.eu } } ltm monitor https /Common/hm_myra_eucaptcha_https { adaptive disabled defaults-from /Common/https destination *:* interval 20 ip-dscp 0 recv HTTP/1 recv-disable none send "GET / HTTP/1.1\r\nHost: api.eu-captcha.eu\r\nConnection: close\r\n\r\n" time-until-up 0 timeout 21 } ltm pool /Common/pool_eucaptcha_api { members { /Common/node-api.eu-captcha.eu:https { } } monitor /Common/hm_myra_eucaptcha_https } ltm profile server-ssl /Common/server-api.eu-captcha.eu { app-service none defaults-from /Common/serverssl server-name api.eu-captcha.eu sni-default true } ltm virtual /Common/vs_dod_eucaptcha_sb { destination 10.10.10.8:webcache ip-protocol tcp mask 255.255.255.255 pool /Common/pool_eucaptcha_api profiles { /Common/http { } /Common/server-api.eu-captcha.eu { context serverside } /Common/tcp { } } serverssl-use-sni enabled source 0.0.0.0/0 source-address-translation { type automap } translate-address enabled translate-port enabled } Note: This configuration creates the necessary node, pool, Server SSL profile (with SNI enabled), and the internal Virtual Server vs_dod_eucaptcha_sb Merge this configuration into your BIG-IP via tmsh: tmsh load sys config merge file /var/tmp/eucaptcha-sideband-vs.conf 2. Generate Your Local HMAC Key To ensure the integrity of the banner acceptance cookie, generate a robust random string on your BIG-IP bash shell: openssl rand -hex 32 3. Deploy the iRule Create a new iRule on your BIG-IP and paste the source code. You must update the RULE_INIT block with your specific values: when RULE_INIT { set static::dod_banner_ttl 600 set static::dod_banner_hmac_key "PASTE_YOUR_OPENSSL_HEX_KEY_HERE" set static::eucaptcha_sitekey "YOUR_EUCAPTCHA_SITEKEY" set static::eucaptcha_secret "YOUR_EUCAPTCHA_SECRET" set static::eucaptcha_sideband_vs "vs_dod_eucaptcha_sb" # Trusted proxy CIDRs (empty = IP::client_addr only). Ex. : list "10.0.0.0/8" set static::dod_banner_trusted_proxy_cidrs [list] # Max acceptations / IP / window (seconds) set static::dod_banner_accept_rate_limit 10 set static::dod_banner_accept_rate_window 60 } Note: The HTML payload is embedded in the iRule and handles the frontend display and token submission. 4. Attach to your Virtual Server Attach the iRule to the public-facing Virtual Server protecting your application. Validation & Testing Open an Incognito/Private browsing window and navigate to your application. You should be intercepted by the DoD warning banner containing the EU CAPTCHA widget. Solve the challenge. The "I Accept" (J'ai pris connaissance et j'accepte) button will enable. Submit the form. The BIG-IP will validate the token via sideband, generate an HMAC-signed _si_gate cookie, and redirect you to the application. Refresh the page; the banner should be bypassed as long as the cookie remains valid (default 600 seconds). Credits Special thanks to Eric Haupt for the original repository that made this possible: https://github.com/hauptem/F5-LTM-iRule-based-DoD-Banners77Views0likes0CommentsForm Based Authentication with external SOAP web services
Problem this snippet solves: 1- You need to authenticate users against an external authentication system relying on SOAP calls. 2- The session identifier must be provided by an external third party system. How to use this snippet: Installation Files You need to upload an html login page using ifiles. You need to upload the SOAP body of the external web service using ifiles. irule You need to install the irule on your Virtual Server you need to protect. Variables set static::holdtime 3600 # session timeout set static::login_url "/login" # login url set static::sideband_vs "VS_EXTERNAL_AUTH_PROVIDER" # Virtual Server that publish the web service Features Version 1.0 Form based login (provided by a custom ifile) Authentication against an external SOAP web service Manage Session timeout Backlog Improve logging Allow 2-factor authentication (Challenge) Encrypt Session cookie Provide internal mecanism to generate a session cookie accept Basic Authentication External links Github : https://github.com/e-XpertSolutions/f5 Code : when RULE_INIT { set static::holdtime 3600 set static::login_url "/login" set static::sideband_vs "VS_EXTERNAL_AUTH_PROVIDER" } when HTTP_REQUEST { if { [HTTP::cookie exists SessionCook] and [table lookup -subtable "active_sessions" [HTTP::cookie SessionCook]] != "" } { return } else { if { [HTTP::path] eq $static::login_url } { if { [HTTP::method] eq "POST" } { if {[HTTP::header "Content-Length"] ne "" && [HTTP::header "Content-Length"] <= 1048576}{ set content_length [HTTP::header "Content-Length"] } else { set content_length 1048576 } if { $content_length > 0} { HTTP::collect $content_length } } else { HTTP::respond 200 content [ifile get login.html] "Cache-Control" "no-cache, must-revalidate" "Content-Type" "text/html" } } else { HTTP::respond 302 noserver "Location" $static::login_url "Cache-Control" "no-cache, must-revalidate" Set-Cookie "SessionCook=$result;domain=[HTTP::host];path=/" } } } when HTTP_REQUEST_DATA { set payload [HTTP::payload] set username "" set password "" regexp {Login1\%3AtxtUserName\=(.*)\&Login1\%3AtxtPassword\=(.*)\&Login1\%3AbtnSubmit\=(.*)} $payload -> username password garbage if {[catch {connect -timeout 1000 -idle 30 -status conn_status $static::sideband_vs} conn_id] == 0 && $conn_id ne ""}{ log local0. "Connect returns: $conn_id and conn status: $conn_status" } else { log local0. "Connection could not be established to sideband_virtual_server" } set content [subst -nocommands -nobackslashes [ifile get soap_body]] set length [string length $content] set data "POST /apppath/webservicename.asmx HTTP/1.1\r\nHost: www.hostname.com\r\nContent-Type: text/xml; charset=utf-8\r\nContent-Length: $length\r\nSOAPAction: http://schemas.microsoft.com/sqlserver/2004/SOAP\r\n\r\n$content" set send_bytes [send -timeout 1000 -status send_status $conn_id $data] set recv_data [recv -timeout 1000 $conn_id] # parse response to retrieve the authentication result, it gives 0 if authentication failed or a session_id if it succeed regexp { (.*) (.*)} $recv_data -> result garbage unset content unset length unset data unset recv_data close $conn_id # add a custom alert notification to the login page if { $result == 0 } { set alert " Invalid credentials. " HTTP::respond 200 content [subst -nocommands -nobackslashes [ifile get login.html]] "Cache-Control" "no-cache, must-revalidate" "Content-Type" "text/html" Set-Cookie "SessionCook=deleted;expires=Thu, 01-Jan-1970 00:00:10 GMT;domain=[HTTP::host];path=/" } else { HTTP::respond 302 noserver "Location" "/" "Cache-Control" "no-cache, must-revalidate" Set-Cookie "SessionCook=$result;domain=[HTTP::host];path=/" # save the cookie value in a cache for fast checking table add -subtable "active_sessions" $result $username indef $static::holdtime } } Tested this on version: 11.5627Views0likes1CommentiRules LX Sideband Connection
Problem this snippet solves: Sideband connections in traditional TCL iRules can be large, complex and difficult to support. Additionally doing something with the information retrieved (such as JSON) may require the use of regular expressions to parse the content before it can be used, something to be avoided if at all possible due to the performance overhead. Using the inbuilt capabilities of Node.js, sideband calls in iRules LX are much easier to implement and with a range of inbuilt as well as NPM packages, the possibilities are endless. To make the external request, the example uses 'https' package from the standard library, however many more are available via NPM such as 'request' which is much simpler to use and doesn't need to chuck the response. The advantage of using the standard library in this instance is this can be done 'out of the box' and doesn't require the use of NPM. In this simple example, a traditional iRule requests the object 'title', which is a JSON object from a publicly available API (https://jsonplaceholder.typicode.com/). { "userId": 1, "id": 1, "title": "delectus aut autem", "completed": false } iRules LX will, make the call using the standard 'https' library, parse the JSON data and return the value for 'title' to the calling iRule, which will be then returned to the user as an HTTP response How to use this snippet: Add the following iRule to yout iRules LX Workspace. This will make an RPC call to iRules LX, using the plugin 'ilx_pl' and the extension 'ilx_ext' You can however call this what you like providing your update the ILX::init command to reflect this. when HTTP_REQUEST { # pass argument to ILX in form of a requested JSON object: # {"userId": 1,"id": 1,"title": "delectus aut autem","completed": false} set arg title set ilx_handle [ILX::init "ilx_pl" "ilx_ext"] if {[catch {ILX::call $ilx_handle "httpRequest" $arg} result]} { log local0.error "Client - [IP::client_addr], ILX failure: $result" HTTP::respond 400 content "<html>There has been an error.</html>" return } HTTP::respond 200 content $result log local0. "retrieved parsed JSON value for $arg: $result" } Use the iRules LX code below for the index.js file, within your workspace Code : var https = require("https"); var f5 = require("f5-nodejs"); var ilx = new f5.ILXServer(); function httpRequest (req, res) { https.get('https://jsonplaceholder.typicode.com/todos/1', function (resp) { var data = ''; // A chunk of data has been recieved. resp.on('data', function (chunk) { data += chunk; }); // The whole response has been received. Parse JSON resp.on('end', function () { res.reply(JSON.parse(data).title); }); }).on("error", function (err) { console.log("Error: " + err.message); }); } ilx.addMethod('httpRequest', httpRequest); ilx.listen(); Tested this on version: 12.11.9KViews2likes1Comment