Forum Discussion
Conditional SNAT using an iRule on a Wildcard Forwarding VS
Hello everyone,
I am new to iRules and have seen a lot of answers to the issue i am currently facing, but even after referring them and trying out all the possible combinations i just can't seem to get it to work.
I have two Viprions (v11.5.1 Hotfix 5) in Active/Standby and a host (with a private address) setup behind those in our lab. The customer would like to connect to a public server to fetch updates. I used a wildcard forwarding VS with a SNAT pool to set this up and it works just fine. Now, he would also like to see a log entry (containing his host's IP, the SNATed IP, and the IP of the public server he is connecting to) whenever an outbound connection is initiated. Additionally, if the public server is on-campus, there should be 'no SNAT log' and 'forwarding', but if the server is off-campus, there has to be 'SNAT log entry' and 'forwarding'.
I looked up conditional SNAT and sure enough there was a solution, but most of them were for CLIENT_ACCEPTED events, which is not the case here. It is more of a SERVER_CONNECTED event. I started by creating two data-groups - 'on-campus networks (public networks and the 172.16/12 prefix routed on campus)' and 'load balanced networks (3 private subnets)' and use these in my iRule. Mind you the 3 private load balanced subnets are taken out of the private /12 routed on campus.
My iRule:-
when SERVER_CONNECTED {
if {[matchclass [clientside {IP::client_addr}] equals loadBalancer_networks] and [matchclass [serverside {IP::remote_addr}] equals onCampus_networks]} {
snat none
return
}
else {
log local0. "Client [clientside {IP::client_addr}]:[clientside {TCP::client_port}] SNATed to [IP::local_addr]:[TCP::local_port] connecting to [serverside {IP::remote_addr}]:[serverside {TCP::remote_port}]"
snatpool snat_pool
}
}
I have tried all the possible IP combinations inside the if statement, but none of them have worked out so far. Can anyone here help me out with the same. Please. Thank you.
15 Replies
- Mohamed_Lrhazi
Altocumulus
When we connected the the "server", snat or no snat had already been decided, no? we are already "connected"!! - nitass
Employee
as Mohamed suggested, you have to use CLIENT_ACCEPTED because SERVER_CONNECTED is too late. additionally, you may try class command instead of matchclass. class https://clouddocs.f5.com/api/irules/class.html alternatively, you may create 2 virtual servers; 0.0.0.0/0 and 172.16.0.0/12, then use snatpool on 0.0.0.0/0 but none on 172.16.0.0/12. both are listening on host (private address) vlan. - aj1
Nimbostratus
Thank you Mohamed and nitass for the prompt reply. This https://devcentral.f5.com/questions/logging-outgoing-snat-list-connections is what i am trying to do, that is logging outbound coonections from the load balanced server. And as you can see, Stephan has suggested to use the SERVER_CONNECTED event to OP. I am following the same approach in that i have a wildcard forwarding vs and a SNAT pool, and now would like to have a log entry onlu when the backend server (three internal vlans) initiates a connection to a public server that is outside our campus network. Please let me know if you need any other info. Thanks.
- nitass
Employee
e.g.
configuration [root@ve11a:Active:In Sync] config tmsh list ltm virtual fwd ltm virtual fwd { destination 0.0.0.0:0 mask any profiles { fastL4 { } } rules { qux } source 0.0.0.0/0 translate-address disabled translate-port disabled vlans { v423 } vlans-enabled vs-index 4 } [root@ve11a:Active:In Sync] config tmsh list ltm rule qux ltm rule qux { when CLIENT_ACCEPTED { if { [class match -- [IP::local_addr] equals onCampus_networks] } { snat none } else { snatpool snat_pool } } when SERVER_CONNECTED { log local0. "Client [IP::client_addr]:[TCP::client_port] \ SNATed to [IP::local_addr]:[TCP::local_port] \ connecting to [IP::remote_addr]:[TCP::remote_port]" } } [root@ve11a:Active:In Sync] config tmsh list ltm data-group internal onCampus_networks ltm data-group internal onCampus_networks { records { 192.168.206.0/23 { } } type ip } [root@ve11a:Active:In Sync] config tmsh list ltm snatpool snat_pool ltm snatpool snat_pool { members { 172.28.24.228 } } /var/log/ltm [root@ve11a:Active:In Sync] config tail -f /var/log/ltm Nov 24 08:41:28 ve11a info tmm[14890]: Rule /Common/qux : Client 200.200.200.111:42810 SNATed to 172.28.24.228:42810 connecting to 8.8.8.8:8 Nov 24 08:41:38 ve11a info tmm[14890]: Rule /Common/qux : Client 200.200.200.111:43066 SNATed to 200.200.200.111:43066 connecting to 192.168.207.56:8 - nitass
Employee
When i used the irule above, received the following logs. I never see a log when a the server initiates an outbound connection.
can't you manually initiate traffic from server? if you do not see the log, you may try to capture traffic (i.e. tcpdump) when testing.
- aj1
Nimbostratus
Thank you so much nitass. Did a tcpdump and i can see the traffic passing the tmm interfaces and the log entries in /var/log/ltm. The ltm log looks exactly like the one you have posted.
Nov 24 23:36:02 slot1/isb-alb-b1 info tmm[10669]: Rule /Common/snat_ipForward : Server 210.96.220.70:512 SNATed to 210.96.220.70:512 connecting to 198.82.149.36:8 Nov 24 23:36:03 slot1/isb-alb-b1 info tmm[10669]: Rule /Common/snat_ipForward : Server 172.28.51.4:15260 SNATed to 198.82.215.251:15260 connecting to 8.8.8.8:8One last question. The second log entry in the above log is the only one i would like to see. The first log entry is not really SNAT(ing) the address, and kinda ends up cluttering our syslog servers. Is there anyway i can get rid of that in the same irule.
PS: I didn't use "class match" in my rule and did bunch of OR's instead. The class match didn't work out here. Not sure if this has something to do with the data-group containing multiple records.
Thanks!
- nitass
Employee
Is there anyway i can get rid of that in the same irule.
you may set variable in CLIENT_ACCEPTED and then check it in SERVER_CONNECTED.
e.g.
root@(ve11a)(cfg-sync In Sync)(Active)(/Common)(tmos) list ltm rule qux ltm rule qux { when CLIENT_ACCEPTED { if { [class match -- [IP::local_addr] equals onCampus_networks] } { set is_snat 0 snat none } else { set is_snat 1 snatpool snat_pool } } when SERVER_CONNECTED { if { $is_snat } { log local0. "Client [IP::client_addr]:[TCP::client_port] \ SNATed to [IP::local_addr]:[TCP::local_port] \ connecting to [IP::remote_addr]:[TCP::remote_port]" } } }The class match didn't work out here. Not sure if this has something to do with the data-group containing multiple records.
can you post the data group?
tmsh list ltm data-group internal (name) - aj1
Nimbostratus
ltm data-group internal onCampus_networks { records { 129.172.0.0/16 { } 172.16.0.0/12 { } 192.82.0.0/16 { } } type ip } - aj1
Nimbostratus
Hi nitass,
Apologize for bothering you again. Everything works greats and now the customer wants to have specific nodes (in the private 172.x) range SNAT'ed to a specific public address from the SNAT pool. I realize this is doable but wondering if i can accommodate this requirement in my current iRule. Any help appreciated.
Thanks!
- nitass
Employee
you can use snat command (and provide snat ip you want source addressto be translated to). snat https://clouddocs.f5.com/api/irules/snat.html
- aj1
Nimbostratus
Thank you for the quick response. I tried the above link, but that is SNATing in the opposite direction (outside client to inside server). I can confirm the same from tcpdump and the logs.
irule:
when CLIENT_ACCEPTED { if { [IP::addr [IP::local_addr] equals 172.27.50.5/32] } { set is_snat 1 snat 197.81.211.230 } elseif {[class match -- [IP::local_addr] equals onCampus_networks]} { set is_snat 0 snat none } else { set is_snat 1 snatpool snat_pool } } when SERVER_CONNECTED { if {$is_snat} { log local0. "Server [IP::client_addr]:[TCP::client_port] SNATed to [IP::local_addr]:[TCP::local_port] for connecting to [IP::remote_addr]:[TCP::remote_port]" } }tcpdump:
tcpdump -nni 0.0 -s0 "(host 172.27.50.5 and icmp)" 16:30:00.904799 IP 198.82.162.116 > 172.27.50.5: ICMP echo request, id 34882, seq 512, length 76 in slot1/tmm2 lis= 16:30:00.904853 IP 197.81.211.230 > 172.27.50.5: ICMP echo request, id 34882, seq 512, length 76 out slot1/tmm2 lis=/Common/vs_wildcard_forwarding 16:30:00.905081 IP 172.27.50.5 > 197.81.211.230: ICMP echo reply, id 34882, seq 512, length 76 in slot1/tmm1 lis= 16:30:00.905951 IP 172.27.50.5 > 198.82.162.116: ICMP echo reply, id 34882, seq 512, length 76 out slot1/tmm2 lis=/Common/vs_wildcard_forwarding- nitass
Employee
in client-side event such as CLIENT_ACCEPTED, IP::local_addr is destination ip and IP::remote_addr or IP::client_addr is source (client) ip. in server-side event such as SERVER_CONNECTED, IP::local_addr is source ip (snat'ed ip) and IP::remote_addr or IP::server_addr is destination (server/pool member) ip.
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