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