Forum Discussion

daboochmeister's avatar
Mar 27, 2015

iRule "virtual" command to use virtual server as pool member - how does it work? Typical event lifecycle?

Per SOL10379 (https://support.f5.com/kb/en-us/solutions/public/10000/300/sol10379.html), starting with 9.4, it's possible for a virtual server to use another virtual server on the same device as a pool member, using the iRules "virtual" command.

 

When this is done, does the normal event processing occur for both virtual servers involved? That is, from an event lifecycle perspective, will it act just as if the virtual server that is a pool member were being accessed externally?

 

In our situation, we have an APM OAM AAA server applied to an HTTP port 80 virtual server; we would like to establish an SSL offload virtual server on the same device, that uses the port 80 virtual server as a pool member. But I'm not clear on whether the port 80 virtual server's event lifecycle for request processing, APM policy processing, etc. will all occur. We're observing some strange behavior, and are exploring if this may be a root cause.

 

thx!

 

2 Replies

  • Hi,

    referencing another virtual server via the
    virtual
    command should go through all protocol stack layers and trigger all related events.

    Instead using another virtual server on the same unit as a pool member is not supported and did not work in most BIG-IP/TMOS versions I know. At least it was not designed to work this way, afaik.

    Terminating SSL on the incoming virtual server and referencing another VS via iRule should be fine in my opinion and working as you expect.

    Thanks, Stephan
  • Hi David,

    I remember some discussions about internal "shortcuts" avoiding packet encapsulation in favour of performance optimization.

    But these should not impact the protocol stack evaluation and iRule processing.

    For testing and validation you can apply the following iRule additionally to both your external (front) and internal virtual server:
    when CLIENT_ACCEPTED {
        log local0. "virtual.name <[virtual name]>;time <[clock clicks -milliseconds]>;"
        log local0. "ip.src <[clientside {IP::remote_addr}]>;tcp.srcport <[clientside {TCP::remote_port}]>;"
        log local0. "ip.dst <[clientside {IP::local_addr}]>;tcp.dstport <[clientside {TCP::local_port}]>;"
    }
    when CLIENT_DATA {
        log local0. "virtual.name <[virtual name]>;time <[clock clicks -milliseconds]>;"
    }
    when HTTP_REQUEST {
        log local0. "virtual.name <[virtual name]>;time <[clock clicks -milliseconds]>;"
    }
    when HTTP_REQUEST_DATA {
        log local0. "virtual.name <[virtual name]>;time <[clock clicks -milliseconds]>;"
    }
    when HTTP_REQUEST_SEND {
        log local0. "virtual.name <[virtual name]>;time <[clock clicks -milliseconds]>;"
    }
    when HTTP_RESPONSE {
        log local0. "virtual.name <[virtual name]>;time <[clock clicks -milliseconds]>;"
    }
    when HTTP_RESPONSE_DATA {
        log local0. "virtual.name <[virtual name]>;time <[clock clicks -milliseconds]>;"
    }
    when LB_SELECTED {
        log local0. "virtual.name <[virtual name]>;time <[clock clicks -milliseconds]>;"
    }
    when SERVER_CONNECTED {
        log local0. "virtual.name <[virtual name]>;time <[clock clicks -milliseconds]>;"
        log local0. "ip.src <[serverside {IP::local_addr}]>;tcp.srcport <[serverside {TCP::local_port}]>;"
        log local0. "ip.dst <[serverside {IP::remote_addr}]>;tcp.dstport <[serverside {TCP::remote_port}]>;"
    }
    when SERVER_DATA {
        log local0. "virtual.name <[virtual name]>;time <[clock clicks -milliseconds]>;"
    }
    when SERVER_CLOSED {
        log local0. "virtual.name <[virtual name]>;time <[clock clicks -milliseconds]>;"
    }
    when CLIENT_CLOSED {
        log local0. "virtual.name <[virtual name]>;time <[clock clicks -milliseconds]>;"
    }
    

    The external virtual server in my example terminates SSL and uses a second iRule as follows to pick an internal virtual server and to apply SNAT (optional).

    when HTTP_REQUEST priority 400 {
        log local0. "virtual.name <[virtual name]>;time <[clock clicks -milliseconds]>;"
        virtual vs_internal_102_80
        snat automap
    }
    

    The log entries below prove the iRule processing on both virtual servers:

     tail -n 0 -f /var/log/ltm | awk -F 'Rule ' '{print $2}'
    /Common/rule_order_testing : virtual.name ;time <1427541193286>;
    /Common/rule_order_testing : ip.src <10.131.131.178>;tcp.srcport <36940>;
    /Common/rule_order_testing : ip.dst <10.131.131.101>;tcp.dstport <443>;
    /Common/rule_vs_select_snat : virtual.name ;time <1427541193309>;
    /Common/rule_order_testing : virtual.name ;time <1427541193309>;
    /Common/rule_order_testing : virtual.name ;time <1427541193309>;
    /Common/rule_order_testing : virtual.name ;time <1427541193309>;
    /Common/rule_order_testing : ip.src <10.131.131.178>;tcp.srcport <23289>;
    /Common/rule_order_testing : ip.dst <10.131.131.102>;tcp.dstport <80>;
    /Common/rule_order_testing : virtual.name ;time <1427541193309>;
    /Common/rule_order_testing : virtual.name ;time <1427541193309>;
    /Common/rule_order_testing : ip.src <10.131.131.178>;tcp.srcport <23289>;
    /Common/rule_order_testing : ip.dst <10.131.131.102>;tcp.dstport <80>;
    /Common/rule_order_testing : virtual.name ;time <1427541193309>;
    /Common/rule_order_testing : virtual.name ;time <1427541193310>;
    /Common/rule_order_testing : virtual.name ;time <1427541193316>;
    /Common/rule_order_testing : virtual.name ;time <1427541193316>;
    /Common/rule_order_testing : virtual.name ;time <1427541193316>;
    

    For the internal virtual server I used a reflector iRule as described here:

    iRule to emulate web server in lab environment (plaintext version)

    Some excellent reading about order of iRule event processing can be found in Steven Iveson´s posts (aka What Lies Beneath) here:

    iRule Event Order - HTTP

    iRule Event Order - HTTPS/SSL - Client & Server Side

    I hope, this answers your question.

    Thanks, Stephan