APM VPN Bandwidth Controller iApp

Problem this snippet solves:

Overview

This iApp will create a set of virtual servers to apply a Bandwidth Controller policy to VPN tunnel traffic.


Example

iperf without the iApp:

$ iperf -c 10.20.20.3
------------------------------------------------------------
Client connecting to 10.20.20.3, TCP port 5001
TCP window size: 64.0 KByte (default)
------------------------------------------------------------
[  3] local 10.20.20.131 port 5957 connected with 10.20.20.3 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.0 sec   184 MBytes   154 Mbits/sec

iperf with 10Mbps dynamic policy

$ iperf -c 10.20.20.3
------------------------------------------------------------
Client connecting to 10.20.20.3, TCP port 5001
TCP window size: 64.0 KByte (default)
------------------------------------------------------------
[  3] local 10.20.20.131 port 6066 connected with 10.20.20.3 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.2 sec  12.1 MBytes  9.98 Mbits/sec

iperf with 1Gbps dynamic policy

$ iperf -c 10.20.20.3
------------------------------------------------------------
Client connecting to 10.20.20.3, TCP port 5001
TCP window size: 64.0 KByte (default)
------------------------------------------------------------
[  3] local 10.20.20.131 port 6569 connected with 10.20.20.3 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.0 sec   190 MBytes   159 Mbits/sec


Function

This creates a set of virtual servers listening on the VPN tunnel with an iRule assigned which applies the BWC policy to both upload and download traffic. You can change your BWC rate as you require, it will be applied to new flows ie users don't have to reconnect.


This has been tested that it deploys and works on v13 but I have not tested this in a production environment, therefore you should test its usage prior to implementation in a production environment. If you have successfully tested it then please PM with details and/or suggestions.

How to use this snippet:

Usage Instructions

This assumes that you already have a VPN configured


  • Create a Bandwidth Controller Policy with the overall bandwidth for the WHOLE VPN, and enable Dynamic if you want to specify the bandwidth for each user.

In the example below, the Maximum Rate of 20Mbps is applied to the whole VPN and 10Mbps is applied to each flow.


  • Load the iApp template at iApps>Templates and Import
  • Deploy a new iApp service at iApps>Application Services>Applications and select the apm_bwc_iapp template



  • Select the VPN tunnel and the Default BWC policy
  • Select any SNAT requirements
  • If you want to apply different rates to different traffic then add entries in the Protocol-specific Bandwidth Controller table. If you don't want to add these then click the X to remove the default entry.
  • Hit Finished


Objects created:


Code :

cli admin-partitions {
    update-partition Common
}
sys application template /Common/apm_bwc_iapp {
    actions {
        definition {
            html-help {
            }
            implementation {
                set app_dir [tmsh::pwd]
				set app_name $tmsh::app_name
                # https://support.f5.com/csp/article/K54955814
                set rule_tcp {when CLIENT_ACCEPTED {
    BWC::policy attach <%=$bwc_policy%> "[IP::remote_addr]:[TCP::remote_port]"
}

when SERVER_CONNECTED {
    BWC::policy attach <%=$bwc_policy%> "[IP::remote_addr]:[TCP::remote_port]"
}
}
                set rule_udp {when CLIENT_ACCEPTED {
    BWC::policy attach <%=$bwc_policy%> "[IP::remote_addr]:[UDP::remote_port]"
}

when SERVER_CONNECTED {
    BWC::policy attach <%=$bwc_policy%> "[IP::remote_addr]:[UDP::remote_port]"
}

}
                if { $::main__use_snat == "Automap" } {
                    set snat "source-address-translation \{ type automap \} " 
                } elseif { $::main__use_snat == "SNAT Pool" } {
                    set snat "source-address-translation \{ type snat pool $::main__snatpool \} "
                } else {
                    set snat ""
                }
                # Create default iRule 
                tmsh::create ltm rule rule_bwc_${app_name}_udp_default [ tmsh::expand_macro $rule_udp -vars "bwc_policy \"$::main__bwc_policy\"" ]
                tmsh::create ltm rule rule_bwc_${app_name}_tcp_default [ tmsh::expand_macro $rule_tcp -vars "bwc_policy \"$::main__bwc_policy\"" ]

                # Create default VS
                tmsh::create ltm virtual vs_bwc_${app_name}_udp_default ip-protocol udp vlans-enabled vlans replace-all-with \{ $::main__tunnel \} destination 0.0.0.0:any mask any $snat profiles replace-all-with \{ udp \} rules \{ rule_bwc_${app_name}_udp_default \} source 0.0.0.0/0 translate-address disabled translate-port disabled
                tmsh::create ltm virtual vs_bwc_${app_name}_tcp_default ip-protocol tcp vlans-enabled vlans replace-all-with \{ $::main__tunnel \} destination 0.0.0.0:any mask any $snat profiles replace-all-with \{ tcp \} rules \{ rule_bwc_${app_name}_tcp_default \} source 0.0.0.0/0 translate-address disabled translate-port disabled

                # Create custom ports and iRules
                foreach {row} $::main__entries {
                    array set cols [lindex $row 0]
                    # protocol, port and bwc_policy
                    set rulename "rule_bwc_${app_name}_$cols(protocol)_$cols(port)"
                    set vsname "vs_bwc_${app_name}_$cols(protocol)_$cols(port)"
                    if { $cols(protocol) == "tcp" } {
                        tmsh::create ltm rule $rulename [tmsh::expand_macro $rule_tcp -vars "bwc_policy \"$cols(bwc_policy)\"" ]
                        tmsh::create ltm virtual $vsname ip-protocol tcp vlans-enabled vlans replace-all-with \{ $::main__tunnel \} destination 0.0.0.0:$cols(port) mask any $snat profiles replace-all-with \{ $cols(protocol) \} rules \{ $rulename \} source 0.0.0.0/0 translate-address disabled translate-port disabled
                    } else {
                        tmsh::create ltm rule $rulename [tmsh::expand_macro $rule_udp -vars "bwc_policy \"$cols(bwc_policy)\"" ]
                        tmsh::create ltm virtual $vsname ip-protocol udp vlans-enabled vlans replace-all-with \{ $::main__tunnel \} destination 0.0.0.0:$cols(port) mask any $snat profiles replace-all-with \{ $cols(protocol) \} rules \{ $rulename \} source 0.0.0.0/0 translate-address disabled translate-port disabled
                    }


                }
            }
            macro {
            }
            presentation {
                section main {
					# The entry below creates a large text box that must be filled out with a valid IP Address
					# For details of APL, look at the iApps developers guide:
					# https://support.f5.com/kb/en-us/products/big-ip_ltm/manuals/product/bigip-iapps-developer-11-4-0.html
					message intro "This iApp will create a forwarding virtual server on the specified VPN tunnel which intercepts the traffic and assigns a BWC policy"

                    choice tunnel display "large" tcl {
							package require iapp 1.1.0
							return "[iapp::get_items net tunnel]"
					}
                    choice bwc_policy display "large" tcl {
							package require iapp 1.1.0
							return "[iapp::get_items -norecursive net bwc policy]"
					}
                    choice use_snat display "large" default "None" { "None" => "None", "Automap" => "Automap", "SNAT Pool" => "SNAT Pool" }
                    optional (use_snat == "SNAT Pool") {
                        choice snatpool display "large" tcl {
							package require iapp 1.1.0
							return "[iapp::get_items ltm snatpool]"
					    } 
                    }
                    table entries {
                        choice protocol display "large" default "tcp" { "tcp" => "tcp", "udp" => "udp" }
                        string port display "large" required validator "PortNumber" default "443"
                        choice bwc_policy display "large" tcl {
							package require iapp 1.1.0
							return "[iapp::get_items -norecursive net bwc policy]"
					    }
                    }
				}

				text {
					# Entities below set the text for the questions and section names, etc. Make them simple and relevant.
					main "Main"
                    main.intro "Usage"
					main.tunnel "VPN Tunnel"
					main.bwc_policy "Default BWC Policy"
                    main.use_snat "Source Address Translation"
                    main.snatpool "SNAT Pool"
                    main.entries "Protocol-specific Bandwidth Controller"
                    main.entries.protocol "Protocol"
                    main.entries.port "Port"
                    main.entries.bwc_policy "BWC Policy"   

				}
            }
            role-acl none
            run-as none
        }
    }
    description "iApp to create an outgoing VS to apply a BWC policy to VPN user traffic v2"
    ignore-verification false
    requires-bigip-version-max none
    requires-bigip-version-min none
    requires-modules { apm }
    signing-key none
    tmpl-checksum none
    tmpl-signature none
}

Tested this on version:

13.0
Published Apr 21, 2020
Version 1.0

Was this article helpful?

No CommentsBe the first to comment