Skip to content

Instantly share code, notes, and snippets.

@ogarrett
Created May 9, 2013 10:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ogarrett/5546803 to your computer and use it in GitHub Desktop.
Save ogarrett/5546803 to your computer and use it in GitHub Desktop.
iPlanet/SunONE/SunJavaSystem module to update internal record of connection source IP address to match value of X-Cluster-Client-IP header from Stingray Traffic Manager
/*---------------------------------------------------------------------
*
* Copyright (c) 2005 Zeus Technology
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Zeus Technology nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* iprewrite.c -- NSAPI module to understand the X-Cluster-Client-Ip
* header, and feed it into the sn->client->ip field
*
* Editing history
* 2005-12-02: Zeus Technology. Initial version (owen@zeus.com)
*
NSAPI iprewrite SAF
===================
This NSAPI SAF inspects the value of the X-Cluster-Client-IP header.
If the connection has come from a trusted IP address (such as a ZXTM
traffic manager), it replaces sn->client->ip with this value.
Initialise this module using 'iprewrite-init'.
You can call the 'iprewrite-all' SAF at the start of request
processing (i.e., AuthTrans). This will modify the Session
object, replacing the value of the 'ip' field in the client pblock
structure. Modifications will persist for the duration if the
session, but other modules may change this value later, or may notice
the discrepancy.
A less invasive alternative is to use the 'iprewrite-func' SAF to
modify the environment for a single nsapi SAF. The change only
persists for that single SAF.
Recommended usage:
#----------------------------------------------------------------------
# magnus.conf:
Init fn="load-modules" \
funcs="iprewrite-init,iprewrite-all,iprewrite-func" \
shlib="/opt/iplanet6/plugins/libiprewrite.so"
Init fn="iprewrite-init" TrustedIPs="10.100.1.1 10.100.1.2"
# obj.conf: Using iprewrite-all
<Object name="default">
AuthTrans fn="iprewrite-all"
</Object>
# obj.conf: Using iprewrite-func
<Object name="weblogic" ppath="star/weblogic/star">
Service fn=iprewrite-func func=wl_proxy \
WebLogicHost=localhost WebLogicPort=7001 PathTrim="/weblogic"
</Object>
In star/weblogic/star, replace 'star' with '*' (C-commenting problem!)
#----------------------------------------------------------------------
Compilation:
cc -Kpic -I/opt/iplanet6/plugins/include \
-DNET_SSL -DSOLARIS -D_REENTRANT -DMCC_HTTPD -DXP_UNIX -DSPAPI20 \
-c iprewrite.c
ld -G -o libiprewrite.so iprewrite.o
For other platforms, copy the compilation options used when making the
samples in /opt/iplanet6/plugins/nsapi/examples/
---------------------------------------------------------------------*/
#include <string.h>
#include <stdlib.h>
#include <nsapi.h>
/* must be in lower (Netscape) case */
static char* zxtmheader = (char*)"x-cluster-client-ip";
/* Module-global configuration */
static pblock *trusted_ips = 0;
static int trust_all_ips = 0;
/* Given a client session, check that it is authorized against the
* TrustedIPs value. Note that different client sessions (with
* different X-Cluster-Client-IP headers) may be multiplexed down
* the same HTTP connection */
static int authorized( Session *sn )
{
const char *trusted = 0;
if( trust_all_ips ) {
return 1;
}
trusted = pblock_findval( "zxtm-trusted", sn->client );
if( trusted ) return ( trusted[0] == 'Y' );
if( trusted_ips ) {
const char* remote_ip = pblock_findval( "ip", sn->client );
if( remote_ip && pblock_findval( remote_ip, trusted_ips ) ) {
pblock_nvinsert( "zxtm-trusted", "Y", sn->client );
return 1;
}
}
pblock_nvinsert( "zxtm-trusted", "N", sn->client );
return 0;
}
/* Read the TrustedIPs configuration and build the internal
configuration */
int iprewrite_init( pblock *args, Session *sn, Request *rq )
{
const char *iplist = pblock_findval( "TrustedIPs", args );
if( !iplist ) {
log_error( LOG_MISCONFIG, (char*)"iprewrite_init", sn, rq,
(char*)"No TrustedIPs configured. Disabling this module." );
return REQ_ABORTED;
}
if( strcmp( iplist, "*" ) == 0 ) {
log_ereport( LOG_INFORM,
(char*)"iprewrite_init: Trusting all remote clients." );
trust_all_ips = 1;
} else {
char *l = strdup( iplist );
char *ptrptr = 0;
char *ip = strtok_r( l, (char*)" ", &ptrptr );
trusted_ips = pblock_create( 4 );
while( ip ) {
pblock_nvinsert( ip, "", trusted_ips );
log_ereport( LOG_INFORM, (char*)"iprewrite-init: Trusting %s", ip );
ip = strtok_r( 0, (char*)" ", &ptrptr );
}
free( l );
}
return REQ_PROCEED;
}
/* Modify the sn->client->ip value for the rest of the client session */
int iprewrite_all( pblock *args, Session *sn, Request *rq )
{
char* x_cluster_client_ip;
x_cluster_client_ip = 0;
request_header( zxtmheader, &x_cluster_client_ip, sn, rq );
if( !x_cluster_client_ip ) return REQ_NOACTION; /* header missing */
if( ! authorized( sn ) ) {
log_ereport( LOG_WARN, (char*)"Ignoring X-Cluster-Client-Ip '%s' from non-Load Balancer machine '%s'",
x_cluster_client_ip, pblock_findval( "ip", sn->client ) );
return REQ_NOACTION;
}
pblock_nvinsert( "ip", x_cluster_client_ip, sn->client );
pblock_nvinsert( "dns", x_cluster_client_ip, sn->client );
return REQ_NOACTION;
}
/* Modify the sn->client->ip value for the named function call only */
int iprewrite_func( pblock *args, Session *sn, Request *rq )
{
char* x_cluster_client_ip;
char* func;
pblock* newargs;
int ret;
int auth = 0;
func = pblock_findval( "func", args );
if( !func ) {
log_ereport( LOG_INFORM, (char*)"iprewrite-func: no func provided" );
return REQ_ABORTED;
}
newargs = pblock_dup( args );
pblock_nvinsert( "fn", func, newargs );
param_free( pblock_remove( "func", newargs ));
x_cluster_client_ip = 0;
request_header( zxtmheader, &x_cluster_client_ip, sn, rq );
if( x_cluster_client_ip ) {
if( ! authorized( sn ) ) {
log_ereport( LOG_WARN, (char*)"Ignoring X-Cluster-Client-Ip '%s' from non-Load Balancer machine '%s'",
x_cluster_client_ip, pblock_findval( "ip", sn->client ) );
ret = func_exec( newargs, sn, rq );
} else {
char *real_ip = pblock_findval("ip", sn->client);
char *real_dns = pblock_findval("dns", sn->client);
pblock_nvinsert( "ip", x_cluster_client_ip, sn->client );
if( real_dns ) pblock_nvinsert( "dns", x_cluster_client_ip, sn->client );
ret = func_exec( newargs, sn, rq );
pblock_nvinsert( "ip", real_ip, sn->client );
if( real_dns ) pblock_nvinsert( "dns", real_dns, sn->client );
}
} else {
/* no x_cluster_client_ip */
ret = func_exec( newargs, sn, rq );
}
pblock_free( newargs );
return ret;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment