Forum Discussion

shawmcbigdis_84's avatar
shawmcbigdis_84
Icon for Nimbostratus rankNimbostratus
Jul 23, 2009

SNAT iRule problem

I'm trying to get snat to work for only outbound internet connections, not for internal addresses. I am using the following rule;

 

 

when SERVER_CONNECTED {

 

 

Compare destination address with the pre-defined

 

class of RFC1918 non-routable addresses

 

If not in that group, automap-SNAT the connection

 

 

log local0. "in SERVER_CONNECTED with [IP::server_addr]"

 

 

if {not [matchclass [IP::server_addr] equals ::private_net] } {

 

snat automap

 

log local0. "[IP::client_addr] client address"

 

log local0. "[IP::local_addr] local address"

 

}

 

}

 

 

the rule does not throw any errors, but the snat is not functioning. When I have this rule as in place on our default rout VIP with SNAT off on the VIP it logs the client and local IP's as the IP of the physical box. When I turn snat on on hte VIP it logs the local ip of the BigIP for the client address (and NAT'ing works obviously)

 

 

I'm pretty new to, and not very good at this whole iRule thing, so I'm sure it's something little that I'm missing.

 

 

Thanks

8 Replies

  • I believe the problem is that the SERVER_CONNECTED event indicates that the server connection has already been established, so it's too late to SNAT at that point. You probably need to implement your logic for SNATing within CLIENT_ACCEPTED.

     

     

    Denny
  • Hi Shawn,

     

     

    The SERVER_CONNECTED event is too late to change the SNAT configuration as the serverside connection has already been established. It should work if you change to LB_SELECTED which is triggered when a load balancing decision has been made. You would also want to use LB::server to get the IP address of the selected destination host instead of IP::server_addr.

     

     

    [Edit: as Denny pointed out, if this is a VIP with address translation disabled (like a forwarding VIP), you could use CLIENT_ACCEPTED and IP::local_addr to check the destination IP address.]

     

     

    That said, you could probably define two separate virtual servers--one enabled only on the external VLAN for external clients and one on the internal VLAN only for internal clients. You could then enable SNAT only on the one virtual server.

     

     

    Aaron
  • Denny and Aaron,

     

     

    I changed the rule based on your suggestions to look like this;

     

     

    when CLIENT_ACCEPTED {

     

     

    Compare destination address with the pre-defined

     

    class of RFC1918 non-routable addresses

     

    If not in that group, automap-SNAT the connection

     

     

    log local0. "in CLIENT_ACCEPTED with [IP::local_addr]"

     

     

    if {not [matchclass [IP::local_addr] equals ::private_net] } {

     

    snat automap

     

    log local0. "[IP::client_addr] client address"

     

    log local0. "[IP::server_addr] server address"

     

    }

     

    }

     

     

    This still isn't functioning properly. in the log I get the following results;

     

     

    Rule outboundSNAT : in CLIENT_ACCEPTED with 74.125.19.147

     

    Rule outboundSNAT : 172.18.16.34 client address

     

    01220001:3: TCL error: outboundSNAT - Error: No serverside connection established (line 10) invoked from within "IP::server_addr"

     

     

    I don't think that error is a problem, since it's just on the log line, but the fact remains that it is still not NAT'ing the connection. And yes, this is on a forwarding VIP. Perhaps I should explain our issue,

     

     

    Basically we have an the Big IP behind a firewall, the switch with all the internal VLAN's connects both to the BigIP and directly to the firewall (for internal networking reasons). So when clients behind the BigIP (which all use the BigIP as their default gateway) try to go to the internet, the packet goes out just fine but when it comes back in the firewall grabs the packet and shoots it directly at the switch. Thus we need the BigIP to NAT those outbound internet connections only.

     

     

    Thanks

     

  • Try changing IP::server_addr in your log statement to IP::local_addr.

     

     

    Aaron
  • Aaron, that worked perfectly! I don't understand why though? Why would a log statement stop the NAT from functioning properly?

     

     

    Also none of those log statements sow me the translated address, which is what I was hoping for, just to verify the log. But the fact that I am getting traffic back to the server is a pretty good verification :-)

     

     

    Shawn
  • IP::server_addr tries to return the remote address from the serverside connection. Because no serverside connection has been established in CLIENT_ACCEPTED, the runtime error (in the log statement) causes an invalid state for the connection. TMM sends a reset to the client to close the connection. To handle runtime errors gracefully and prevent resets, you can use the catch command(Click here).

    If you want to see the source IP:port translation, you could add the log statements back to the SERVER_CONNECTED event:

     
     when CLIENT_ACCEPTED { 
      
         Debug logging 
        log local0. "[IP::client_addr]:[TCP::client_port]: New TCP connection to destination IP:port [IP::local_port]:[TCP::local_port]" 
      
         Compare destination address with the pre-defined 
         class of RFC1918 non-routable addresses 
         If not in that group, automap-SNAT the connection 
        if {not [matchclass [IP::local_addr] equals ::private_net] } { 
           snat automap 
        } 
     } 
     when SERVER_CONNECTED { 
      
         Debug logging 
        log local0. "[IP::client_addr]:[TCP::client_port]: New TCP connection to destination IP:port [IP::local_port]:[TCP::local_port] \ 
           using source [IP::local_addr]:[TCP::local_port]" 
     } 
     

    For more details on the IP:: and TCP:: commands and context, you can check this post:

    http://devcentral.f5.com/Default.aspx?tabid=53&forumid=5&tpage=1&view=topic&postid=1018710235

    And the events wiki page:

    http://devcentral.f5.com/wiki/default.aspx/iRules/events

    Aaron
  • OK, got it. Awesome. Thanks a ton for the help.

     

     

    I need to know one last thing. How can I verify that this isn't NAT'ing incoming connections? I mean, a client out on the internet makes a request for one of the websites behind the bigIP. The initial request is to a routable IP, but it hits the firewall first, and then the firewall makes the request to the non-routable IP of the VIP. So that iRule, is not going to even be functioning on that VIP, correct? And also by the time the connection request gets to the BigIP, it can't even see that the original request was for a routable IP. Right? I just need to verify because there are parts of our app that need to verify the connecting clients IP, and if it NAT's the incoming, that would not work at all.

     

     

    Shawn
  • What VIPs do you have defined that could potentially match the destinations? Clients will only be able to connect to one virtual server for the full request and response to LTM and to the pool member. The iRule would only be triggered for virtual servers that it is configured for under the VIP's resources tab in the GUI.

     

     

    Aaron