A practical guide to limiting bandwidth in QRadar
The bandwidth manager in IBM® QRadar® takes advantage of the hierarchical token bucket (HTB) queuing discipline that is offered within the Linux kernel. For specifics or more advanced usage, there are many pages on the Internet that describe what it is and how it works, including:
Before you begin, you'll have to tweak the bandwidthManagerCLI.sh file first to change the buildcpath location. To edit the bandwidthManagerCLI.sh file, type edit /opt/qradar/bin/bandwidthManagerCLI.sh. Change the third line in the file to read /opt/qradar/systemd/bin/buildcpath. Save and close the file.
Bandwidth Manager help and usage
The following code snippet lists the usage of the Bandwidth Manager:
[root@m5arch06 ~]# /opt/qradar/bin/bandwidthManagerCLI.sh
usage: BandwidthManagerCLI -a <ACTION>
-a,--action The desired action. Recognized Actions: help, add_class, add_egress_filter,
delete_class, delete_egress_filter
usage: add_class <OPTIONS>
-i,--hostID The managed host ID which uniquely identifies the host. You can optionally
use '-1' to indicate you wish this to be applied to all hosts in the deployment
-n,--name A user-friendly name for the new configuration
-c,--classID The desired class ID of the class to be added
-d,--device The device name (e.g. eth0) which this configuration will apply to. You can
optionally use '*' to indicate you wish to be applied to all devices
-h,--hostname The managed host host name. Can be used when you don't provide the host ID
-k,--kbpsLimit The rate limit to be applied against the class in kilobytes/sec
-p,--parentID The parent ID for this class
-q,--qdiscID The desired queuing discipline ID of the egress filter to be added
usage: add_egress_filter <OPTIONS>
-i,--hostID The managed host ID which uniquely identifies the host. You can
optionally use '-1' to indicate you wish this to be applied to all hosts in the deployment
-n,--name A user-friendly name for the new configuration
-P,--protocol The protocol for the new configuration
-d,--device The device name (e.g. eth0) which this configuration will apply to.
You can optionally use '*' to indicate you wish to be applied to all devices
-dc,--dstCIDR [Optional] The destination CIDR for the egress filter
-dport,--dstPort [Optional] The destination port for the egress filter
-dportm,--dstPortMask [Optional] The destination port mask for the egress filter. If not
provided, 0xffff will be used (meaning match only that port)
-f,--filterID The desired filter ID to be assigned to the new egress filter
-fl,--flowID The filter's target flow ID (which represents the minor ID of a
class or qdisc). Traffic matched by this filter with go to that location
-fp,--filterPriority The fitler's priority relative to others attached to the same parent
(lower number is higher priority)
-h,--hostname The managed host host name. Can be used when you don't provide the
host ID
-ma,--matchAll [Optional] If "true", the filter that is created will match *all*
incoming packets at its priority level.
-p,--parentID The parent ID for this egress filter
-q,--qdiscID The desired queuing discipline ID of the egress filter to be added
-sc,--sourceCIDR [Optional] The source CIDR for the egress filter
-sport,--srcPort [Optional] The source port for the egress filter
-sportm,--srcPortMask [Optional] The source port mask for the egress filter. If not
provided, 0xffff will be used (meaning match only that port)
usage: delete_class <OPTIONS>
-i,--hostID The managed host ID which uniquely identifies the host. You can optionally
use '-1' to indicate you wish this to be applied to all hosts in the deployment
-c,--classID The class ID to class to delete
-d,--device The device name (e.g. eth0) of the configuration to be deleted
-h,--hostname The managed host host name. Can be used when you don't provide the host ID
-q,--qdiscID The queuing discipline ID of the class you wish to delete
usage: delete_egress_filter <OPTIONS>
-i,--hostID The managed host ID which uniquely identifies the host. You can optionally
use '-1' to indicate you wish this to be applied to all hosts in the deployment
-d,--device The device name (e.g. eth0) of the configuration to be deleted
-f,--filterID The filter ID of the filter to delete
-h,--hostname The managed host host name. Can be used when you don't provide the host ID
[root@m5arch06 ~]#
Terminology
- Classes
-
Define chunks of bandwidth – minimums and maximums. They are arranged in a tree structure. For instance, you have a 10 Mbit link that is shared between QRadar and other applications. You want to ensure that QRadar never uses more than 5 Mbit/sec, so it doesn’t saturate the link. You define a class for all traffic that is limited to 5 Mbit/sec and then you can further subdivide that so that your PostgreSQL replication doesn’t affect search performance.
- Filters
-
Select the network traffic that is placed into each of these classes. Typically done by IP/protocol/port combinations, the filters are remarkably flexible and allow very fine granularity – for our purposes, we’ll stick with the simple IP/protocol/port combinations.
Cookbook – Examples
All commands are run on the console – no need to run on a managed host. You specify which host to apply the change to in the bandwidthManagerCLI.sh command line.
Example: Slowing down replication to a host (all port 443 traffic – assuming non-encrypted)
/opt/qradar/bin/bandwidthManagerCLI.sh -a add_class -h m5arch06 -n SlowReplication -c 1 -q 30 -p 0 -k 10 -d eno1
/opt/qradar/bin/bandwidthManagerCLI.sh -a add_egress_filter -h m5arch06 -n MatchHttps -d eno1 -dc 192.0.2.0/32 -f 2 -fl 1 -fp 1 -p 0 -q 30 -sport 443 -P tcp
/opt/qradar/bin/bandwidthManagerCLI.sh -a add_egress_filter -h m5arch06 -n MatchHttps -d eno1 -dc 192.0.2.0/32 -f 3 -fl 3 -fp 1 -p 0 -q 1 -sport 443 -P tcp
….
2750K .......... .......... .......... .......... .......... 4% 9.02K 1h45m
2800K .......... .......... .......... .......... .......... 4% 9.68K 1h45m
2850K .......... .......... .......... .......... .......... 4% 9.51K 1h45m
2900K .......... .......... .......... .......... .......... 4% 8.14K 1h45m
2950K .......... .......... .......... .......... .......... 5% 9.00K 1h45m
3000K .......... .......... .......... .......... .......... 5% 9.00K 1h45m
3050K .......... .......... .......... .......... .......... 5% 9.99K 1h44m
…..
Rates are approximately (and not exceeding) 10 Kbyte/second.
To test and see if the throttling is taking place on the console, look at the output from the class that we set up:
[root@m5arch06 ~]# tc -s class ls dev eno1 classid 30:1
class htb 30:1 root prio 1 rate 80000bit ceil 80000bit burst 1600b cburst 1600b
Sent 8579563 bytes 7315 pkt (dropped 0, overlimits 0 requeues 0)
rate 0bit 0pps backlog 0b 3p requeues 0
lended: 4682 borrowed: 0 giants: 0
tokens: -4730822 ctokens: -4730822
[root@m5arch06 ~]#
To remove the bandwidth rules, type the following commands:
/opt/qradar/bin/bandwidthManagerCLI.sh -a delete_egress_filter -h m5arch06 -d eno1 -f 2
/opt/qradar/bin/bandwidthManagerCLI.sh -a delete_egress_filter -h m5arch06 -d eno1 -f 3
/opt/qradar/bin/bandwidthManagerCLI.sh -a delete_class -h m5arch06 -c 1 -q 30 -d eno1
Example: Limiting all bandwidth between the console and a managed host
We will be monitoring the bandwidth on the console and in the following setup:
- m5arch06 (198.51.100.0) is the console
- m5arch07 (192.0.2.0) is the managed host
/opt/qradar/bin/bandwidthManagerCLI.sh -a add_class -h m5arch06 -n SlowCommunicationToHost -c 1 -q 30 -p 0 -k 10 -d eno1
Add filters to match the class and queuing discipline by typing the following command:
/opt/qradar/bin/bandwidthManagerCLI.sh -a add_egress_filter -h m5arch06 -n MatchToIP -d eno1 -dc 192.0.2.0/32 -f 2 -fl 1 -fp 1 -p 0 -q 30 -P tcp
/opt/qradar/bin/bandwidthManagerCLI.sh -a add_egress_filter -h m5arch06 -n MatchToIP -d eno1 -dc 192.0.2.0/32 -f 3 -fl 3 -fp 1 -p 0 -q 1 -P tcp
If you want to throttle the bandwidth on the managed host (notice the change to the hostname that these apply to and the destination CIDR), type the following command:
/opt/qradar/bin/bandwidthManagerCLI.sh -a add_class -h m5arch07 -n SlowCommunicationToHost -c 1 -q 30 -p 0 -k 10 -d eno1
/opt/qradar/bin/bandwidthManagerCLI.sh -a add_egress_filter -h m5arch07 -n MatchToIP -d eno1 -dc 198.51.100.0/32 -f 2 -fl 1 -fp 1 -p 0 -q 30 -P tcp
/opt/qradar/bin/bandwidthManagerCLI.sh -a add_egress_filter -h m5arch07 -n MatchToIP -d eno1 -dc 198.51.100.0/32 -f 3 -fl 3 -fp 1 -p 0 -q 1 -P tcp
Finally, to delete from both console and managed host, type the following command:
/opt/qradar/bin/bandwidthManagerCLI.sh -a delete_egress_filter -h m5arch06 -d eno1 -f 2
/opt/qradar/bin/bandwidthManagerCLI.sh -a delete_egress_filter -h m5arch06 -d eno1 -f 3
/opt/qradar/bin/bandwidthManagerCLI.sh -a delete_class -h m5arch06 -c 1 -q 30 -d eno1
/opt/qradar/bin/bandwidthManagerCLI.sh -a delete_egress_filter -h m5arch07 -d eno1 -f 2
/opt/qradar/bin/bandwidthManagerCLI.sh -a delete_egress_filter -h m5arch07 -d eno1 -f 3
/opt/qradar/bin/bandwidthManagerCLI.sh -a delete_class -h m5arch07 -c 1 -q 30 -d eno1
Example: Adding the changes via SQL and poking Mbeans in order for the changes to take effect (a bit quicker and more scriptable)
This example uses the same configuration as in the first example, but we insert into PostgreSQL instead of waiting for the bandwidth manager to initialize frameworks and do all that work for us.
- The bandwidth_configuration table contains all of the class / bandwidth information:
qradar=# \d bandwidth_configuration
Table "public.bandwidth_configuration" Column | Type | Modifiers ----------------+------------------------+------------------------------------------------------------ sequenceid | bigint | not null default nextval('bandwidth_configuration_seq'::regclass) appname | character varying(100) | not null mh_id | bigint | not null device | character varying(100) | not null qdisc_id | integer | not null class_id | integer | not null parent_id | integer | not null bandwidth_kbps | bigint | not null created_by | character varying(100) |
- The bandwidth_egress_filter contains all of the
filters:
qradar=# \d bandwidth_egress_filter
Table "public.bandwidth_egress_filter" Column | Type | Modifiers -----------------+------------------------+----------------------------------------------------------- sequenceid | bigint | not null default nextval('bandwidth_egress_filter_seq'::regclass) appname | character varying(100) | not null mh_id | bigint | not null device | character varying(100) | not null qdisc_id | integer | not null parent_id | integer | not null filter_id | integer | not null flow_id | integer | not null filter_priority | integer | not null src_port | integer | src_port_mask | integer | src_cidr | character varying(45) | dst_port | integer | dst_port_mask | integer | dst_cidr | character varying(45) | match_all | boolean | not null default false created_by | character varying(100) | protocol | character varying(4) |
Using the configuration from example 1, we end up with SQL that looks like the following snippet:
INSERT INTO bandwidth_configuration (appname, mh_id, device, qdisc_id, class_id, parent_id, bandwidth_kbps, created_by) VALUES ('SlowReplication', 53, 'eno1', 30, 1, 0, 10, 'SQL_Insert');
INSERT INTO bandwidth_egress_filter (appname, mh_id, device, qdisc_id, parent_id, filter_id, flow_id, filter_priority, src_port, src_port_mask, dst_cidr, created_by, protocol) VALUES ('MatchHttps', 53, 'eno1', 30, 0, 2, 1, 1, 443, 65535, '192.0.2.0/32', 'SQL_Insert', 'ip');
INSERT INTO bandwidth_egress_filter (appname, mh_id, device, qdisc_id, parent_id, filter_id, flow_id, filter_priority, src_port, src_port_mask, dst_cidr, created_by, protocol) VALUES ('MatchHttps', 53, 'eno1', 1, 0, 3, 3, 1, 443, 65535, '192.0.2.0/32', 'SQL_Insert', 'ip');
Now, we poke the Mbean and refresh its configuration:
[root@m5arch06 ~]# /opt/qradar/support/jmx.sh 7778 'com.q1labs.hostcontext.bm:application=hostcontext.hostcontext,type=BandwidthManager' reloadConfig
Invoking operation: reloadConfig ( )
Result: true
[root@m5arch06 ~]#
And voila! The class is back:
[root@m5arch06 ~]# tc class ls dev eno1
class prio 1:1 parent 1: leaf 10:
class prio 1:2 parent 1: leaf 20:
class prio 1:3 parent 1: leaf 30:
class prio 1:4 parent 1: leaf 40:
class prio 1:5 parent 1: leaf 50:
class prio 1:6 parent 1: leaf 60:
class prio 1:7 parent 1: leaf 70:
class htb 30:1 root prio 1 rate 80000bit ceil 80000bit burst 1600b cburst 1600b
[root@m5arch06 ~]#
Then we delete the entries in the database and reload again:
[root@m5arch06 ~]# psql -U qradar -c "DELETE from bandwidth_configuration"
DELETE 1
[root@m5arch06 ~]# psql -U qradar -c "DELETE from bandwidth_egress_filter"
DELETE 2
[root@m5arch06 ~]# /opt/qradar/support/jmx.sh 7778 'com.q1labs.hostcontext.bm:application=hostcontext.hostcontext,type=BandwidthManager' reloadConfig
Invoking operation: reloadConfig ( )
Result: true
[root@m5arch06 ~]#
And voila! The class disappears again:
[root@m5arch06 ~]# tc class ls dev eno1
class prio 1:1 parent 1: leaf 10:
class prio 1:2 parent 1: leaf 20:
class prio 1:3 parent 1: leaf 30:
class prio 1:4 parent 1: leaf 40:
class prio 1:5 parent 1: leaf 50:
class prio 1:6 parent 1: leaf 60:
class prio 1:7 parent 1: leaf 70:
[root@m5arch06 ~]#