Forum Discussion
Checkpoint Web Smartconsole behind reverse proxy.
Does anyone have any experience at trying (and hopefully suceeding) to put a Checkpoint (CP) FW Provider-1 based web smartconsole behind a reverse proxy.
The thing is that CP use local IP addresses to identify one of a selection of management module instances.
And they use webtransport/websockets to connect from these mgmt modules back to a browser for displaying FW policies and log data etc.
That all seems fairly OK but they don't anchor it using the connection ID and so the raw IPs (of what they call the domain blade/instance) get passed to the browser.
But we would prefer to NAT/hide/reIP the server (domain) side IPs and not have the internal server/domain IPs sent along to the browser.
Part of the conversation, and some wrapper text from me, from the server to the client follows:
***
We wish to use access to various customer domains using the /smartconsole web interface. But the access has to be behind a reverse proxy (F5 vIP) and after the initial logon using the CMA IP behind a vIP (so address the browser sees is a service public one) you get a screen where the domain is listed and after selecting continue you get redirected seperately to the CMA IP in an internal JSON/javascript message. Hence breaking the attempt to have the CMA behind a reverse proxy.
***
{"data":{"loginToDomain":{"transportOtt":"107ad894-253d-4638-aa31-1c3e7d23172a","transportUrl":"https://100.64.20.29:443/smartconsole/transport","__typename":"LoginToDomainResponse"}}}
***
1 Reply
- Jeffrey_Granier
Employee
Hi Martyn,
I have not tried this setup before, so please take caution and ensure you test this in a NON-Prod environment.
From a BIG-IP config perspective you will likely need:
- HTTPS VS listening on 443 using a FQDN so smart console traffic comes here first
- Create a pool of all Checkpoint MGT servers, if these are on different servers or use different backend IP's this pool will need to be setup more dynamically. I suggest start with 1 backend first.
- Use a HTTP + Stream + Web Socket Profile ( may need to remove stream profile .. TBD)
- Use SNAT - Auto-Map
- Need's an IruleLX plugin created and an irule to call it... so create the IruleLX first
const f5 = require('f5-nodejs'); const url = require('url'); const ilx = new f5.ILXServer(); ilx.addMethod('rewriteTransportUrl', function(req, res) { const payload = req.params()[0]; // Original JSON string let json; try { json = JSON.parse(payload); } catch (e) { return res.reply(payload); // Return original if invalid JSON } const newHost = req.params()[1]; // External host (e.g., smartconsole.example.com) // Access nested transportUrl if (json.data && json.data.loginToDomain && json.data.loginToDomain.transportUrl) { const oldUrl = url.parse(json.data.loginToDomain.transportUrl); const internalHost = oldUrl.host; // Extract internal host (e.g., 100.64.20.29:443) const ott = json.data.loginToDomain.transportOtt || ''; // Extract OTT // Rewrite host oldUrl.host = newHost; json.data.loginToDomain.transportUrl = url.format(oldUrl); // Return array: [rewritten JSON, OTT, internalHost] res.reply([JSON.stringify(json), ott, internalHost]); } else { res.reply([payload, '', '']); // No match, return original } }); ilx.listen();Now create the Irule:
when RULE_INIT { # Define subtable for OTT mappings (global, with TTL) set static::ott_map_ttl 3600; # 1 hour timeout set static::json_uri_pattern "/smartconsole"; # URI pattern for JSON responses (adjust if specific) } when CLIENT_ACCEPTED { # Initialize iRulesLX handle (once per connection) set rpc_handle [ILX::init "json_rewrite_ws_plugin" "json_rewrite_extension"] } when HTTP_REQUEST { # Handle WebSocket upgrade requests to /smartconsole/transport if { [HTTP::uri] starts_with "/smartconsole/transport" && [HTTP::header exists "Upgrade"] && [string tolower [HTTP::header "Upgrade"]] eq "websocket" } { # Extract OTT from query param (e.g., ?ott=uuid) set ott [URI::query [HTTP::uri] ott] if { $ott ne "" } { # Lookup internal host from table set internal_host [table lookup -subtable "ott_map" $ott] if { $internal_host ne "" } { # Route to the correct node (assume port 443) node [lindex [split $internal_host ":"] 0] 443 } else { # Fallback: reject or default pool reject } } else { # No OTT: reject or log log local0. "WebSocket request without OTT: [HTTP::uri]" reject } } } when HTTP_RESPONSE { # Collect JSON responses for rewriting (check URI or Content-Type) if { [HTTP::header Content-Type] contains "application/json" && [HTTP::status] == 200 && [HTTP::uri] contains $static::json_uri_pattern } { HTTP::collect [HTTP::header Content-Length] } } when HTTP_RESPONSE_DATA { # Call iRulesLX to rewrite JSON and extract OTT/internalHost set payload [HTTP::payload] set result [ILX::call $rpc_handle "rewriteTransportUrl" $payload [HTTP::host]] # Result is list: {rewritten_json ott internal_host} set rewritten_json [lindex $result 0] set ott [lindex $result 1] set internal_host [lindex $result 2] if { $ott ne "" && $internal_host ne "" } { # Store mapping in table table set -subtable "ott_map" $ott $internal_host $static::ott_map_ttl } # Replace payload with rewritten JSON HTTP::payload replace 0 [string length $payload] $rewritten_json }Ensure the irule is applied to the VS and give it a go... I have not tested this out so there may be plenty of errors.
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