Forum Discussion
specific source port translation
Hi,
I am trying to do SNAT while selecting a specific port for that but for some reason when the F5 receive the response it is sending a RST to the WS and not retranslating it to the original IP and port.
I configured the below:
when CLIENT_ACCEPTED {
set PublicIP 10.107.200.200
snat $PublicIP 12345
}
I can see that connection was created:
VIRTUAL any <-> NODE 173.194.47.19:80 TYPE any 1/3
CLIENTSIDE 10.107.200.140:51251 <-> 173.194.47.19:80
(pkts,bits) in = (2, 120) out = (0, 0)
SERVERSIDE 10.107.200.200:12345 <-> 173.194.47.19:80
(pkts,bits) in = (0, 0) out = (2, 120)
PROTOCOL 6 UNIT 1 IDLE 2 (300) LASTHOP WDN_MIG_Internal 00:14:5e:a8:0a:04
This the tcpdump from the F5:
19:22:02.182260 IP 10.107.200.200.12345 > 173.194.47.19.80: S 1731136945:1731136945(0) win 5840
19:22:02.264415 IP 173.194.47.19.80 > 10.107.200.200.12345: S 718544173:718544173(0) ack 1731136946 win 1460
19:22:02.264439 IP 10.107.200.200.12345 > 173.194.47.19.80: R 1:1(0) ack 1 win 0
Do you have any idea why the F5 behave in that way?
Thanks a lot.
34 Replies
- schmal_111133
Nimbostratus
When I tried to disable the CMP it still didn't worked, but let me try again and I will check it and update soon. - nitass
Employee
When I tried to disable the CMP it still didn't worked, but let me try again and I will check it and update soon.how did you disable cmp? is it on virtual server or global? would it be possible to disable it globally? - schmal_111133
Nimbostratus
I disabled it on a VS but now after checking it, the traffic still returned to different tmm.
Now I will disable it globally and check it.
do you know if the packet should return to the same TMM or that the SNAT should work across the TMM no matter to which TMM the SYN ACK returned? - nitass
Employee
do you know if the packet should return to the same TMM or that the SNAT should work across the TMM no matter to which TMM the SYN ACK returned?i understand return packet must go to the same tmm which packet is sent. in cmp, i understand source port is allocated (by hashing) to make sure return packet will come to correct tmm. - schmal_111133
Nimbostratus
ok, now when I disabled the tmm globally it looks much better actually it is working exactly as expected!
Probably F5 have some issue with the hash that select the tmm when the SYN ACK arrived, I will mention it in the case and see what they have to say about it.
Thanks a lot for all the help here!! :) - nitass
Employee
Probably F5 have some issue with the hash that select the tmm when the SYN ACK arrivedi understand the issue is expected because we force to use specific snat port. normally, bigip will select snat port to ensure return packet will be hashed to the same tmm packet is sent out.
When CMP is enabled on the system, the BIG-IP system may modify the client source port for virtual server or SNAT connections in order to ensure that both client and server-side flows are hashed to the same TMM instance. This issue can occur even when the TM.PreserveClientPort database variable is set to enabled.sol8227: The BIG-IP system may modify the client source port for virtual server connections when Clustered Multi-Processing is enabled
http://support.f5.com/kb/en-us/solutions/public/8000/200/sol8227.html - schmal_111133
Nimbostratus
So based on that what is the purpose of using the port in the SNAT command if it will not ensure that the return packet will arrive to the same TMM? - nitass
Employee
So based on that what is the purpose of using the port in the SNAT command if it will not ensure that the return packet will arrive to the same TMM?i understand snat port option has existed before introducing cmp.
if you want to use specific snat port, for example, 12345, it might be possible to forward client-side traffic to specific tmm which will handle port 12345 on server-side. - nitass
Employee
if you want to use specific snat port, for example, 12345, it might be possible to forward client-side traffic to specific tmm which will handle port 12345 on server-side.not sure if this is a good idea. anyway, i did a little bit test as following.
bar is virtual server which receives client traffic. then if tmm for port 12345 is the one which traffic is coming, apply snat and send it out normally. otherwise, send traffic to specific tmm throught tmm_vs.[root@B3900-R72-S18:Active] config b virtual bar list virtual bar { translate address enable destination any:any mask 0.0.0.0 rules bar_rule } [root@B3900-R72-S18:Active] config b rule bar_rule list rule bar_rule { when RULE_INIT { set static::tmm_num [TMM::cmp_count] set static::srcip "200.200.200.18" set static::srcport 12345 } when CLIENT_ACCEPTED { set tmm_in [TMM::cmp_unit] set tmm_out [expr {($static::srcport ^ [TCP::local_port]) % $static::tmm_num}] log local0. "incoming | client [IP::client_addr]:[TCP::client_port] server [IP::local_addr]:[TCP::local_port] tmm $tmm_in" if {$tmm_in == $tmm_out} { set ps_local 1 snat $static::srcip $static::srcport node [IP::local_addr] } else { set ps_local 0 node 127.10.1.[expr {$tmm_out + 1}] } } when SERVER_CONNECTED { if {$ps_local} { log local0. "outgoing | client [IP::local_addr]:[TCP::local_port] server [IP::remote_addr]:[TCP::remote_port] tmm [TMM::cmp_count]" } else { table set "[IP::local_addr]:[TCP::local_port]" [clientside {IP::local_addr}] } } } [root@B3900-R72-S18:Active] config b virtual tmm_vs list virtual tmm_vs { translate address enable destination 126.0.0.0:any mask 254.0.0.0 rules tmm_rule } [root@B3900-R72-S18:Active] config b rule tmm_rule list rule tmm_rule { when CLIENT_ACCEPTED { snat $static::srcip $static::srcport node [table lookup "[IP::client_addr]:[TCP::client_port]"] } when SERVER_CONNECTED { log local0. "otugoing | client [IP::local_addr]:[TCP::local_port] server [IP::remote_addr]:[TCP::remote_port] tmm [TMM::cmp_unit]" } } test [root@B3900-R72-S18:Active] config tail -f /var/log/ltm Feb 15 22:58:15 local/tmm3 info tmm3[5371]: Rule bar_rule : incoming | client 100.100.100.1:43677 server 172.28.19.251:22 tmm 3 Feb 15 22:58:15 local/tmm3 info tmm3[5371]: Rule bar_rule : outgoing | client 200.200.200.18:12345 server 172.28.19.251:22 tmm 4 Feb 15 22:58:24 local/tmm1 info tmm1[5369]: Rule bar_rule : incoming | client 100.100.100.1:38558 server 172.28.19.251:23 tmm 1 Feb 15 22:58:24 local/tmm2 info tmm2[5370]: Rule tmm_rule : otugoing | client 200.200.200.18:12345 server 172.28.19.251:23 tmm 2 Feb 15 22:58:30 local/tmm3 info tmm3[5371]: Rule bar_rule : incoming | client 100.100.100.1:55203 server 172.28.19.251:80 tmm 3 Feb 15 22:58:30 local/tmm1 info tmm1[5369]: Rule tmm_rule : otugoing | client 200.200.200.18:12345 server 172.28.19.251:80 tmm 1 Feb 15 22:58:34 local/tmm info tmm[5368]: Rule bar_rule : incoming | client 100.100.100.1:39711 server 172.28.19.251:443 tmm 0 Feb 15 22:58:34 local/tmm2 info tmm2[5370]: Rule tmm_rule : otugoing | client 200.200.200.18:12345 server 172.28.19.251:443 tmm 2 - schmal_111133
Nimbostratus
Hi Nitass,
Just now I saw your comment, so thanks again for your effort to reply 🙂
I didn't exactly understood how you can determine which TMM will handle the traffic when the traffic return to the F5 and not leaving it..
Let me explain you what I need to achieve.
We have a demand to do the following:
do kind of a static SNAT from private IP to Public IP and source port from a range of ports. for example:
192.168.0.1 --> 203.0.113.1:1024-5055
192.168.0.2 --> 203.0.113.1:5056-9087
192.168.0.3 --> 203.0.113.1:9087-13119
192.168.0.4 --> 203.0.113.1:13120-17151
192.168.0.5 --> 203.0.113.1:17152-21183
of course there are more than one public IP..
and so on..
This idea come in order to be able to know who was the private IP based on the public IP and port without the need of logging.
Now I wrote a irule that do that, you can review it and comment if you have better ideas:[root@LBA-F5-1A:Active] config b rule SNAT list rule SNAT { when RULE_INIT { log local0.alert "Building new SNAT configuration" Build the SNAT IPs ---------------------------------------------------------- Configure the name of the SNAT pool here set static::snatpool_name "SNAT_Pool" Hide the members command from the iRule parser (BZ381099 comment 7) set static::members_cmd "members -list $static::snatpool_name" Clear any pre-existing array of the same name unset -nocomplain static::snat_ips unset -nocomplain static::SNAT Define the port block size set static::BlockSize 1000 Define the amount of private IPs for one Public IP set static::AmountPrivateInPublic 3 define the start port set static::StartPort 2000 Loop through the SNAT pool members and add them to an array for faster access If the SNAT pool is modified, the RULE_INIT code needs to be re-run to re-read the SNAT pool Make a simple change like adding a space to a comment to force a re-run of RULE_INIT. foreach static::snat_ip [eval $static::members_cmd] { set static::IP [lindex $static::snat_ip 0] for {set j 0} {$j < $static::AmountPrivateInPublic} {incr j} { for {set i 0} {$i < $static::BlockSize} {incr i} { lappend static::SNAT(${static::IP},$j) [expr {$i + $static::StartPort + ($static::BlockSize*($j))}] } } } Clear the variables we will not use anymore unset static::snatpool_name static::members_cmd static::snat_ip i j ---------------------------------------------------------------------------------------- } when CLIENT_ACCEPTED { log local0.alert "Private IP --> [IP::client_addr]:[TCP::client_port] -- " set PublicIP "[class search -value PrivateToPublic eq [IP::client_addr]]" set PortBlock "[class search -index PrivateToPublic eq [IP::client_addr]]" set PortBlock [expr {$PortBlock % $static::AmountPrivateInPublic}] Check if the Private IP exist in the class if { $PublicIP eq "" }{ snatpool SNAT_Default return } set static::PortNum [lindex $static::SNAT($PublicIP,$PortBlock) 0] log local0.alert "Private IP --> [IP::client_addr]:[TCP::client_port] Public IP --> $PublicIP:$static::PortNum" Do SNAT with the selected public IP & port snat $PublicIP $static::PortNum Remove the port from the List of ports set static::SNAT($PublicIP,$PortBlock) [lreplace $static::SNAT($PublicIP,$PortBlock) 0 0] } when SERVER_CLOSED { Check if the SNATed IP exist in the class if { [class match [IP::local_addr] eq SNAT_Default] }{ return } Finding the port block number set BlockNum [expr {(([TCP::local_port] - $static::StartPort) / $static::BlockSize)} ] log local0.alert "Closing Connection --> [IP::local_addr]:[TCP::local_port] Block --> $BlockNum " Adding the port back to the pool of available ports lappend static::SNAT([IP::local_addr],$BlockNum) [TCP::local_port] } } [root@LBA-F5-1A:Active] config b class PrivateToPublic list class PrivateToPublic { { "192.168.0.1" { "203.0.113.1" } "192.168.0.2" { "203.0.113.1" } "192.168.0.3" { "203.0.113.1" } "192.168.0.4" { "203.0.113.1" } "192.168.0.5" { "203.0.113.1" } } } [root@LBA-F5-1A:Active] config b class SNAT_Default list class SNAT_Default { "203.0.113.2" }
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