Forum Discussion

JohnnyG's avatar
JohnnyG
Icon for Nimbostratus rankNimbostratus
Jun 14, 2023
Solved

SNAT IP address logging

Hello,

I am setting up logging to log access to the Virtual servers as we use SNAT addressing to access all internal resources.  It has come about as part of our Security requirements to log all access so that it can be fully traced back to the client that initiated the connection, as the servers they are connecting to will show the SNAT address that was assigned to the client accessing it at the time.  I have created the below iRule which assigns a snatpool to the client then sends the logs to a syslog server, but I am unable to get the SNAT address that is assigned to the client included in the logs

 

when CLIENT_ACCEPTED {
    # Set logging variables
    set vip [IP::local_addr]:[TCP::local_port]
    set reqTime [clock format [clock seconds] -format {%Y/%m/%d %H:%M:%S}]
    set hslHandle [HSL::open -publisher /Common/SNATLog_Publisher]
    # Do the SNAT stuff 
    if { [class match [getfield [IP::client_addr] "%" 1] equals internal_nets] } {
        snatpool snat_pool_internal
}
    else {
        snatpool snat_pool_external
}
}

when SERVER_CONNECTED {
    #Get client and server IPs and Ports
    set client "[clientside {IP::remote_addr}]:[clientside {TCP::remote_port}]"
    set clientip "[IP::local_addr clientside]:[TCP::local_port clientside]"
    set node "[IP::remote_addr]:[TCP::remote_port]"
}

when CLIENT_CLOSED {
    # log connection info
    HSL::send $hslHandle "$reqTime: Client $client -> SNAT: $clientip -> VIP: $vip -> Node: $node"
}

 

 For example - the client has a LAN address of 192.168.0.50 and has been assigned the SNAT address of 10.0.0.50.  It is accessing a server which has a Virtual IP address of 10.10.10.1 and connects to a pool member on 192.168.168.52.  This will generate the logs of:

tmm[23710]: 2023/06/14 08:50:05: Client 192.168.0.50:52293 -> SNAT: 10.10.10.1:443 -> VIP: 10.10.10.1:443 -> Node: 192.168.168.52

It appears that the SNAT address is showing as the VIP address - how do i get it to include the SNAT ip address assigned as part of the snatpool snat_pool_internal ?

  • Hi JohnnyG , 
    Pretty irule first, 

    Why do you add "Clientside" 
    in this Line Code : 

        set clientip "[IP::local_addr clientside]:[TCP::local_port clientside]"
    

    SNAT IP not in the Client side but server side , 
    So Remove it and check again 
    I think it should be like this now : 

    when CLIENT_ACCEPTED {
        # Set logging variables
        set vip [IP::local_addr]:[TCP::local_port]
        set reqTime [clock format [clock seconds] -format {%Y/%m/%d %H:%M:%S}]
        set hslHandle [HSL::open -publisher /Common/SNATLog_Publisher]
        # Do the SNAT stuff 
        if { [class match [getfield [IP::client_addr] "%" 1] equals internal_nets] } {
            snatpool snat_pool_internal
    }
        else {
            snatpool snat_pool_external
    }
    }
    
    when SERVER_CONNECTED {
        #Get client and server IPs and Ports
        set client "[clientside {IP::remote_addr}]:[clientside {TCP::remote_port}]"
        set clientip "[IP::local_addr]:[TCP::local_port]"
        set node "[IP::remote_addr]:[TCP::remote_port]"
    }
    
    when CLIENT_CLOSED {
        # log connection info
        HSL::send $hslHandle "$reqTime: Client $client -> SNAT: $clientip -> VIP: $vip -> Node: $node"
    }
    

    According to this Article : 
    https://clouddocs.f5.com/api/irules/TCP__local_port.html

    I hope this helps you 🙂 
     

6 Replies

  • Hi JohnnyG , 
    Pretty irule first, 

    Why do you add "Clientside" 
    in this Line Code : 

        set clientip "[IP::local_addr clientside]:[TCP::local_port clientside]"
    

    SNAT IP not in the Client side but server side , 
    So Remove it and check again 
    I think it should be like this now : 

    when CLIENT_ACCEPTED {
        # Set logging variables
        set vip [IP::local_addr]:[TCP::local_port]
        set reqTime [clock format [clock seconds] -format {%Y/%m/%d %H:%M:%S}]
        set hslHandle [HSL::open -publisher /Common/SNATLog_Publisher]
        # Do the SNAT stuff 
        if { [class match [getfield [IP::client_addr] "%" 1] equals internal_nets] } {
            snatpool snat_pool_internal
    }
        else {
            snatpool snat_pool_external
    }
    }
    
    when SERVER_CONNECTED {
        #Get client and server IPs and Ports
        set client "[clientside {IP::remote_addr}]:[clientside {TCP::remote_port}]"
        set clientip "[IP::local_addr]:[TCP::local_port]"
        set node "[IP::remote_addr]:[TCP::remote_port]"
    }
    
    when CLIENT_CLOSED {
        # log connection info
        HSL::send $hslHandle "$reqTime: Client $client -> SNAT: $clientip -> VIP: $vip -> Node: $node"
    }
    

    According to this Article : 
    https://clouddocs.f5.com/api/irules/TCP__local_port.html

    I hope this helps you 🙂 
     

    • JohnnyG's avatar
      JohnnyG
      Icon for Nimbostratus rankNimbostratus

      Hi Mohamed,

      Thanks for looking at this for me - not sure why the clientside was added, but removing makes it the same as the value that is being used for the Virtual Server address:

          set vip [IP::local_addr]:[TCP::local_port]
      
          set clientip "[IP::local_addr]:[TCP::local_port]"

      Would that also not duplicate the incorrect IP address in the generated logs ?

      • Hi JohnnyG , 
        No , Because it depends on the which event has been triggered. 

        set vip [IP::local_addr]:[TCP::local_port]


        This will be saved in Variable $vip at Client side.

        But this : 

            set clientip "[IP::local_addr]:[TCP::local_port]"

        this will be saved in variable $clientip when server side connection being established. 

        so both of values are different. 

        Have a look at this Article : https://clouddocs.f5.com/api/irules/TCP__local_port.html
        it proves what I say.

         

  • Mohamed_Ahmed_Kansohhas treated you well here, but will want to point out one more thing. It is possible that the VIP and SNAT will actually be the same. Usually one would use SNAT automap but then it becomes difficult to 'marry' a connection for troubleshooting purposes and of course automap has a 64k limit across all Virtual Server usage. So, the convention is to use Snatpools, but generally one uses the VIP in the pool. This way, the same IP address is seen as "server" on clientside and "client" on serverside. This may actually not be an issue... what IP addresss are in both of the Snatpools? Have you tested this with a client matching internal nets AND a client not matching internal nets? Do you see a different SNAT IP at that time in the logs?

    • Hi whisperer , 
      Thanks , I havn't tested it , but it should work because he uses two different events and 2 variables... 
      SO VIP will give him local IP on Bigip in the client side , and SNAT will give him the local IP on server side. 

      My understanding about Local IP : is something belongs to bigip may be ( SNAT Floating , Self , SNAT pool , Or Listner Virtual server ) but the Local IP will differ depending upon the triggered event on server side or client side. 

      Maybe as you said this little bit tricky , but I have sent to him another iRule with only one event he can use it and will give him same result.

      Did I understand you well ?