Forum Discussion
Chris_Stamm_183
Nimbostratus
Aug 10, 2005RPC load balancing among multiple tiers using iRules, pools and forwarding
Scenario:
We have an app that uses...
TCP port 7496 for one piece.
TCP port 3372 for another piece.
TCP port 135 for DTC that will renegotiate a high port in this case we set the RPC range for AppServerA to 40000 to 40999, AppServerB to 41000 to 41999, AppServerC to 42000 to 42999, AppServerD to 43000 to 43999, AppServerE to 44000 to 44999. We do this so that we can load balance RPC by saying if the port negotiated is between 42000 and 42999 then we know we send that to AppServerD.
Our application is tiered where we have a web layer that is load balanced, an application layer that is load balanced by the above configuration and finally a database layer that does not load balance but does require the same ports as above. The environment looks something like this. BigIP (BigIPWeb) connected on external interface to internet and internal interface to web layer. Bigip (BigIPApp)connected on external interface to web layer and internal interface to app layer. Firewall connected on external interface to app layer and internal interface to database layer.
Incoming web requests are good but here is what I need to do for the app to communicate properly (I am already doing this on 4.5 but 9.x is quite a bit different)...
Web request comes in through BigIPWeb and gets LB'd to WebServerA. WebServerA needs to make request to the application layer VIP on port 7496 initially, then initiates another request to application layer VIP for port 135 (has to be the same VIP for all application layer traffic - not necessarily same node) which will renegotiate depending on the app server that gets the request on 135 - in this instance lets say AppServerA gets the 135 port so the negotiated port must lay between 40000 and 40999. After all that is done one last communication happens which is all from a lower tier to a higher tier i.e. sql to app or app to web.
So to sumarize we need to LB port 7496 to a five nodes, 135 to five nodes, 40000-40999 to AppServerA, 41000 to 41999 to AppServerB, 42000 to 42999 to AppServerC, 43000 to 43999 to AppServerD, 44000 to 4$999 to AppServerE and finally upward traffic on 3372.
I intend on doing this with two iRules which are here...
This is the inbound to app VIP.
APP_POOL will have servers AppServerA, AppServerB, AppServerC, AppServerD, AppServerE.
AppServerA will have AppServerA in pool with port set to 0 (to include all)
AppServerB will have AppServerB in pool with port set to 0 (to include all)
and so on up to AppServerE
VIP is set to this
when CLIENT_ACCEPTED {
if { [TCP::server_port] == 7495 }
{
pool APP_POOL
}
elseif { [TCP::server_port] == 135 }
{
pool APP_POOL
}
elseif { [TCP::server_port] > 39999 and [TCP::server_port] < 41000 }
{
pool AppServerA
}
elseif { [TCP::server_port] > 40999 and [TCP::server_port] < 42000 }
{
pool AppServerB
}
elseif { [TCP::server_port] > 41999 and [TCP::server_port] < 43000 }
{
pool AppServerC
}
elseif { [TCP::server_port] > 42999 and [TCP::server_port] < 44000 }
{
pool AppServerD
}
elseif { [TCP::server_port] > 43999 and [TCP::server_port] < 45000 }
{
pool AppServerE
}
elseif { [TCP::server_port] == 3372 }
{
forward
}
else {
discard
}
}NetworkBasedVIP set to this for access to APP network for DTC forwards and callbacks...
when CLIENT_ACCEPTED {
if { [TCP::server_port] == 7495 }
{
forward
}
elseif { [TCP::server_port] == 135 }
{
forward
}
elseif { [TCP::server_port] > 39999 and [TCP::server_port] < 41000 }
{
forward
}
elseif { [TCP::server_port] > 40999 and [TCP::server_port] < 42000 }
{
forward
}
elseif { [TCP::server_port] > 41999 and [TCP::server_port] < 43000 }
{
forward
}
elseif { [TCP::server_port] > 42999 and [TCP::server_port] < 44000 }
{
forward
}
elseif { [TCP::server_port] > 43999 and [TCP::server_port] < 45000 }
{
forward
}
elseif { [TCP::server_port] == 3372 }
{
forward
}
else {
discard
}
}NetworkBasedVIP set to this for access to DATABASE network for DTC forwards and callbacks...
when CLIENT_ACCEPTED {
if { [TCP::server_port] == 7495 }
{
forward
}
elseif { [TCP::server_port] == 135 }
{
forward
}
elseif { [TCP::server_port] > 39999 and [TCP::server_port] < 41000 }
{
forward
}
elseif { [TCP::server_port] > 40999 and [TCP::server_port] < 42000 }
{
forward
}
elseif { [TCP::server_port] > 41999 and [TCP::server_port] < 43000 }
{
forward
}
elseif { [TCP::server_port] > 42999 and [TCP::server_port] < 44000 }
{
forward
}
elseif { [TCP::server_port] > 43999 and [TCP::server_port] < 45000 }
{
forward
}
elseif { [TCP::server_port] == 3372 }
{
forward
}
else {
discard
}
}13 Replies
- rapmaster_c_127Historic F5 AccountThe issue is one of making the attack harder to perpetrate more than anything else. When any script-kiddie with a connection to the internet can send out an arbitrary SYN packet spoofing its source IP address, we could potentially be evaluating a rule on every last one of those SYNs, with no way of telling whether the SYN is representative of a real client. All someone would have to do is connect to the internet, and spew out hundreds and thousands of SYNs per second at us. If each one of those bare SYNs caused us to have to evaluate a rule, this would be an easy DOS.
By deferring rule evaluation until the 3-way handshake completes, we at least know that the SYN is not spoofed, since the attacker needs to be able to mirror (our sequence number + 1) back in its ACK, and this makes the attack somewhat more difficult, in that the attacker cannot perpetrate a blind-attack against us. - unRuleY_95363Historic F5 AccountIt does seem like you should be able to construct a packet filter for your test and forward rule. You would simply create a forwarding vip with no rule and then create a packet filter that checks the destination is the vip and whether the destination port is in your accepted range and discard if not. That's actually a pretty straight forward packet filter.
You would still need a rule for the node routing part of deployment. - Chris_Stamm_183
Nimbostratus
Agreed. I know you guys are busy and appreciate the time to answer my questions.
As a side note within the iRule, I tried to use...default { reject }
as opposed to...default { discard }
and got the desired behavior for my circumstance. With the discard in there I could enter in anything I wanted much like you could if you used telnet to get into an smtp server and typed ehlo, etc. (not that I could necessarily have done anything but you never know). With the reject in there as soon as I enter in a keystroke it drops my TCP connection.
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)Recent Discussions
Related Content
DevCentral Quicklinks
* 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
Discover DevCentral Connects