Forum Discussion
Universal persistence using header values for multiple client IPs.
Hello all,
I require universal persistence based upon a XFF header value, but for any source IP. The scenario is that an initial client connection hits the F5 and is load balanced to node A (the F5 need to persist to a member in poolA using XFF value received or inserted). Then a back end server makes a connection to the F5 and sends the XFF value that was originally received from the client, targets the same VS but a different poolB. This connection must persist to the same node A as in the separate connection from the client. Is this possible using persist lookup functions?
11 Replies
Hi ajohnson,
please elaborate a little bit more details on your pool/member setup? E.g.: Are both pools using the same set of members but with different ports?
Cheers, Kai
- AlexJ
Nimbostratus
Hello Kai, thanks for the quick response.
So there will be 1 VIP (using proxypass for selecting the target pool). There will be 2 or more pools with the same members to different ports.
Client connection is sent to poolA nodeA (XFF value is used to persist to nodeA). A separate connection from a server needs to be sent to the same nodeA but in poolB, using the XFF header value for persistence.
Kind Regards
Hi ajohnson,
Can you please add dummy IPs and ports to this logic?
Client connection: (SRC_IP: 0.0.0.0/0) -VS: X.X.X.X:XXX -PoolA -Member1: X.X.X.X:XXX -Member2: X.X.X.X:XXX Backend Connection: (SRC_IP: only from Member1 or Member2 to VS2?) -VS: X.X.X.X:XXX -PoolB -Member1: X.X.X.X:XXX -Member2: X.X.X.X:XXXCheers, Kai
- AlexJ
Nimbostratus
Client connection: (SRC_IP: 99.99.99.1/32) -VS: 10.10.10.1:443 (using proxypass to determine pool) -PoolA -Member1: 1.2.3.4:994 - selected as target -Member2: 1.2.3.5:994 Backend Connection: (SRC_IP: 1.2.3.4/32) -VS: 10.10.10.1:443 (using proxypass to determine pool) -PoolB -Member1: 1.2.3.4:499 - this needs to be targeted -Member2: 1.2.3.5:499 Hi ajohnson,
this setup will be somewhat complicated then and requires other/additional coding techniques than using
to team the instances.[persist]What is the reason to forward the backend connection to your F5 if the DST_IP is always the orginating SRC_IP? It would be much easier if the service on 1.2.3.4:994 will always directly connect to 1.2.3.4:499 (aka. 127.0.0.1:499) and the service on 1.2.3.5:994 will always request to 1.2.3.5:499 (aka. 127.0.0.1:499 too)...
Beside of that, it would be good to know how your iRule/LTM Policy configuration selects the different backend pools based on the incomming HTTP requests?
Cheers, Kai
Hi ajohnson,
take a look to the iRule below and tell me what you think?
The iRule uses the
event to differentiate between client and backend connections. If a backend connection is identified, then it will be checked during theCLIENT_ACCEPTED
event ifLB_SELECTED
(currently selected pool member) equals the[LB::server addr]
(backend IP address). If the IPs are matching no action is taken. But if the IPs are different the[IP::client_addr]
will be used as new[IP::client_addr]
by executing the[LB::server addr]
command a second time.[pool]when CLIENT_ACCEPTED { if { ( [IP::client_addr] starts_with "1.2.3.4" ) or ( [IP::client_addr] starts_with "1.2.3.5" ) } then { set backend_connection 1 } else { set backend_connection 0 } } when LB_SELECTED { if { $backend_connection } then { if { [LB::server addr] equals [IP::client_addr] } then { The selected node is already correct... } else { pool [LB::server pool] member [IP::client_addr] [LB::server port] } } else { Use LB decissions / persistence records for client connections. } }Note: The iRule can be combined with any persistence profile / LB algorythm you wish. The backend connection will be overwritten on demand without affecting client connections.
Warning: Didn't tested nor saved the iRule at all. So better apply this iRule on a test-system... 😉
Cheers, Kai
- AlexJ
Nimbostratus
Hello Kai, thanks for the response.
Just a clarification:
"What is the reason to forward the backend connection to your F5 if the DST_IP is always the orginating SRC_IP?"
This is not the case, the only requirements are that the target pool member both be the same for the two separate connections from the client and the server. At present this is how the application has to work, but of course standard load balancing must distribute load.
I am now looking at adding a new header to the clients initial request to the server (containing the target node IP), then when the server request arrives with this header value use it to target the required node, but I would prefer to use universal persistence (persist lookup perhaps) if possible.
Kind Regards
Hi ajohnson,
This is not the case, the only requirements are that the target pool member both be the same for the two separate connections from the client and the server. At present this is how the application has to work, but of course standard load balancing must distribute load.
This means in effectively, that if a client connects initially to NodeA (via Random selection), the NodeA will then always connect its backend connection to itself. Thats why I'm asking if this connection really needs to pass your F5 and I've proposed a solution (see at the very buttom of this page) which doesn't require any
commands at all to team the backend connections.[persist]I am now looking at adding a new header to the clients initial request to the server (containing the target node IP), then when the server request arrives with this header value use it to target the required node, but I would prefer to use universal persistence (persist lookup perhaps) if possible.
Okay... will write you an
iRule with[persist]
options. Should take only a few minutes so stay tuned... 😉Match Across ServiceCheers, Kai
Hi ajohnson,
here we go...
The iRule below uses the
event to differentiate between client and backend connections. If a backend connection is identified, the submittedCLIENT_ACCEPTED
header value (if exist) will be used to query and build theX-Forwarded-For
information. If the backend server does not send a[persist]
header theX-Forwarded-For
of the backend system will be used to query and build the[IP::client_addr]
information. If a client connection is identified, the existing[persist]
headers will become sanitized (may contain untrusted information) and a newX-Forwarded-For
header will be inserted based on theX-Forwarded-For
. The client system will also use its[IP::client_addr]
to to query and build the[IP::client_addr]
information.[persist]when RULE_INIT { set static::xff_persist_timeout 900 ; persist information timeout in seconds } when CLIENT_ACCEPTED { if { ( [IP::client_addr] starts_with "1.2.3.4" ) or ( [IP::client_addr] starts_with "1.2.3.5" ) } then { set trusted_xff_sender 1 } else { set trusted_xff_sender 0 } } when HTTP_REQUEST { if { $trusted_xff_sender } then { if { [HTTP::header value "X-Forwarded-For"] ne "" } then { persist uie [HTTP::header value "X-Forwarded-For"] $static::xff_persist_timeout } else { HTTP::header insert "X-Forwarded-For" [IP::client_addr] persist uie [IP::client_addr] $static::xff_persist_timeout } } else { HTTP::header remove "X-Forwarded-For" HTTP::header insert "X-Forwarded-For" [IP::client_addr] persist uie [IP::client_addr] $static::xff_persist_timeout } }Note: To make this iRule work you have to make sure that your HTTP-Profile does not insert
headers. The insert will be done selectively by the provided iRule. In addition to that, you need to create a custom "Universal Persistence" profile, with theX-Forwarded-For
option selected (see config snippet below). This profile needs to be attached to your Virtual Server.Match Across Serviceltm persistence universal XFF_Persist { app-service none defaults-from universal match-across-services enabled rule none }Note: For further information regarding the
option you may read the solution article K5837.Match Across ServiceCheers, Kai
- AlexJ
Nimbostratus
Hell Kai,
Match across services will not work as the client is not the same and therefore the target pool member selection and resultant persistence entry will be completely independent.
I get your point about the server connecting effectively to itself, but I am told by the app team that there are various reasons why they need to reconnect back through the F5 one of which is the other intelligence the F5 provides through the proxypass configuration.
What I really need is this.
Client makes a connection to the F5, the F5 sets a persistence record to a pool member based upon XFF or another header I insert (maybe containing the selected pool member). Then when the server makes it's connection the F5 will see either the preserved XFF value (or the headre value for the selected pool member in the first connection) and will target the same IP.
I would prefer to use persistence records and lookups if possible as it makes it much easier to support an understand what is happening as the logic will be that the persistence table entry for a client informs the F5 where to send server connections for the same use session.
Many thanks
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)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
