Skip to main content

Low-Bandwidth Optimisation

Low-bandwidth optimisation configures systems to function on connections where available throughput falls below 2 Mbps, latency exceeds 200ms, or packet loss rises above 1%. These constraints characterise satellite links, congested mobile networks, and shared rural connectivity common in field operations. The techniques in this task reduce bandwidth consumption by 40-70% through compression, caching, protocol tuning, and traffic shaping, transforming unusable connections into functional ones.

Prerequisites

RequirementDetail
AccessAdministrative access to proxy servers, network equipment, and endpoint management systems
PermissionsRoot/sudo on Linux systems; local administrator on Windows endpoints; firewall rule modification rights
Toolsiftop, vnstat, tc (iproute2), squid 4.0+, nginx 1.18+
InformationCurrent bandwidth allocation, user count, critical application list, peak usage times
Baseline data7 days of traffic capture showing current consumption patterns
Time4-8 hours for initial configuration; 2 weeks for tuning

Verify required tools are available:

Terminal window
# Check traffic control availability
tc -V
# Expected: tc utility, iproute2-ss200127 or later
# Check Squid version
squid -v | head -1
# Expected: Squid Cache: Version 4.0 or later
# Install monitoring tools if missing
sudo apt install iftop vnstat nethogs

Gather baseline metrics before making changes. Without baseline data, you cannot measure improvement or identify regression.

Terminal window
# Start vnstat monitoring on primary interface
sudo vnstat -u -i eth0
# Capture 7-day baseline
# After 7 days, export summary
vnstat -d -i eth0

Procedure

Phase 1: Traffic analysis and baseline

  1. Capture current bandwidth consumption by protocol and destination. Run this analysis during peak usage hours (typically 09:00-11:00 and 14:00-16:00 local time) to identify actual bottlenecks rather than idle-state behaviour.
Terminal window
# Real-time traffic by connection
sudo iftop -i eth0 -t -s 300 > traffic_baseline.txt
# Capture by process (requires nethogs)
sudo nethogs -t -d 5 eth0 > process_bandwidth.txt &
sleep 300
kill %1

Analyse the output to identify bandwidth consumers. A representative field office with 15 users on a 1 Mbps connection shows consumption patterns like:

Protocol/Service Typical % Target %
Web browsing 35% 20%
Email (with attach) 25% 10%
Cloud sync 20% 5%
Video conferencing 10% 15% (priority)
Software updates 8% 2%
Other 2% 8%
  1. Identify specific high-bandwidth destinations using DNS query analysis and flow data. Extract the top 20 destinations by bandwidth:
Terminal window
# Parse iftop output for top destinations
cat traffic_baseline.txt | grep -E "^[0-9]" | \
sort -t',' -k3 -rn | head -20

Common bandwidth-heavy destinations in mission-driven organisations include cloud storage sync (OneDrive, Google Drive, Dropbox), video platforms (Teams, Zoom, Meet), software update servers (Microsoft, Apple, Linux repositories), and analytics/telemetry endpoints.

  1. Document application-specific bandwidth requirements. For each critical application, measure actual consumption under typical use:
Terminal window
# Isolate single application traffic (example: Teams)
sudo tcpdump -i eth0 -w teams_capture.pcap \
'host 52.112.0.0/14 or host 52.120.0.0/14' &
# Use Teams normally for 30 minutes
kill %1
# Analyse capture
capinfos teams_capture.pcap

Record findings in a bandwidth budget that totals to less than 80% of available link capacity, reserving 20% for burst headroom.

Phase 2: Compression configuration

Compression reduces data volume before transmission. Three compression points exist: application-level (built into software), proxy-level (intermediary compression), and transport-level (VPN or tunnel compression). Apply compression at the highest effective layer to avoid double-compression overhead.

  1. Configure Squid proxy with aggressive compression for web traffic. Create or modify /etc/squid/squid.conf:
# Compression settings for low-bandwidth environments
http_port 3128 ssl-bump generate-host-certificates=on dynamic_cert_mem_cache_size=4MB
# Enable response compression
acl uncompress_response rep_header Content-Encoding gzip
acl uncompress_response rep_header Content-Encoding br
# Force compression for uncompressed responses
adaptation_access compress_response allow !uncompress_response
# Delay pools for bandwidth management (configured in Phase 4)
delay_pools 3
delay_class 1 2
delay_class 2 2
delay_class 3 2
# Memory and disk cache (adjust for available resources)
cache_mem 256 MB
maximum_object_size_in_memory 512 KB
cache_dir ufs /var/spool/squid 10000 16 256
maximum_object_size 100 MB
# Aggressive caching
refresh_pattern -i \.exe$ 43200 100% 43200
refresh_pattern -i \.msi$ 43200 100% 43200
refresh_pattern -i \.zip$ 43200 100% 43200
refresh_pattern -i \.gz$ 43200 100% 43200
refresh_pattern -i \.deb$ 43200 100% 43200
refresh_pattern -i \.rpm$ 43200 100% 43200
refresh_pattern -i \.(gif|png|jpg|jpeg|ico|webp)$ 43200 90% 43200
refresh_pattern -i \.(css|js)$ 1440 90% 43200
refresh_pattern . 0 20% 4320
  1. Enable GZIP compression on nginx reverse proxy (if used for internal applications):
/etc/nginx/conf.d/compression.conf
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_min_length 256;
gzip_types
application/atom+xml
application/javascript
application/json
application/ld+json
application/manifest+json
application/rss+xml
application/vnd.geo+json
application/vnd.ms-fontobject
application/x-font-ttf
application/x-web-app-manifest+json
application/xhtml+xml
application/xml
font/opentype
image/bmp
image/svg+xml
image/x-icon
text/cache-manifest
text/css
text/plain
text/vcard
text/vnd.rim.location.xloc
text/vtt
text/x-component
text/x-cross-domain-policy
text/xml;
  1. Configure transport-level compression for VPN connections. For WireGuard (which does not include compression), use a compressed tunnel wrapper. For OpenVPN, enable LZ4 compression:
# /etc/openvpn/client.conf addition
compress lz4-v2
push "compress lz4-v2"

Compression and encryption

Compression before encryption can leak information through size variations (CRIME/BREACH attacks). For sensitive traffic, disable compression or ensure compression occurs after encryption. The LZ4 configuration above is acceptable for general office traffic but should be disabled for systems handling protection data.

  1. Verify compression effectiveness by comparing transfer sizes:
Terminal window
# Test without compression
curl -so /dev/null -w "%{size_download}" http://example.org/test-page
# Test with compression
curl -so /dev/null -w "%{size_download}" --compressed http://example.org/test-page
# Calculate ratio
# Typical HTML: 70-85% reduction
# Typical JSON: 80-90% reduction
# Already compressed (images, video): 0-5% reduction

Phase 3: Caching implementation

Caching stores frequently accessed content locally, eliminating repeated downloads. A well-configured cache in a 15-person office typically achieves 30-50% hit rate, effectively increasing available bandwidth by that percentage for cacheable content.

+-----------------------------------------------------+
| CACHING ARCHITECTURE |
+-----------------------------------------------------+
| |
| +------------------+ |
| | Internet | |
| | (Constrained) | |
| +--------+---------+ |
| | |
| | 1 Mbps link |
| v |
| +--------+---------+ |
| | Edge Router | |
| | (QoS enforced) | |
| +--------+---------+ |
| | |
| v |
| +--------+---------+ +------------------+ |
| | Squid Proxy |<--->| Local DNS | |
| | Cache | | (with cache) | |
| | | | | |
| | - Web cache | | - Query cache | |
| | - SSL bump | | - Local zones | |
| | - Delay pools | | | |
| +--------+---------+ +------------------+ |
| | |
| v |
| +------------------+ |
| | Local LAN | |
| | (Users/Devices) | |
| +------------------+ |
| |
+-----------------------------------------------------+

Figure 1: Caching architecture for bandwidth-constrained field office

  1. Configure Squid disk cache with appropriate sizing. Allocate 50-100 MB of cache per user, with minimum 2 GB total:
Terminal window
# Calculate cache size
# 15 users × 75 MB = 1,125 MB, round to 2 GB minimum
# Create cache directory
sudo mkdir -p /var/spool/squid
sudo chown proxy:proxy /var/spool/squid
# Initialise cache (in squid.conf, already configured above)
# cache_dir ufs /var/spool/squid 10000 16 256
# This creates 10 GB cache with 16 L1 and 256 L2 directories
# Initialise
sudo squid -z
# Start service
sudo systemctl enable squid
sudo systemctl start squid
  1. Configure Windows Update caching using WSUS or Delivery Optimisation. For environments without WSUS, configure peer-to-peer Delivery Optimisation:
Terminal window
# Configure via Group Policy or direct registry
# HKLM\SOFTWARE\Policies\Microsoft\Windows\DeliveryOptimization
# Enable LAN-only download mode (mode 1)
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DeliveryOptimization" `
-Name "DODownloadMode" -Value 1 -Type DWord
# Set maximum background bandwidth (percentage)
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DeliveryOptimization" `
-Name "DOPercentageMaxBackgroundBandwidth" -Value 10 -Type DWord
# Set maximum foreground bandwidth
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DeliveryOptimization" `
-Name "DOPercentageMaxForegroundBandwidth" -Value 25 -Type DWord
  1. Deploy DNS caching to reduce lookup latency and external queries. Configure dnsmasq or unbound as local resolver:
/etc/dnsmasq.conf
# Cache size (entries, not bytes)
cache-size=10000
# Don't forward plain names
domain-needed
bogus-priv
# Upstream DNS (use organisation's DNS or reliable public DNS)
server=8.8.8.8
server=8.8.4.4
# Local domain
local=/fieldoffice.local/
# DNSSEC validation (if upstream supports it)
dnssec
trust-anchor=.,20326,8,2,E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D
  1. Configure browser caching policies via Group Policy or MDM. Increase local cache sizes and retention:
// Chrome policy (managed preferences)
{
"DiskCacheSize": 524288000,
"MediaCacheSize": 104857600
}

For Firefox, deploy via policies.json:

{
"policies": {
"Preferences": {
"browser.cache.disk.capacity": 512000,
"browser.cache.memory.capacity": 65536
}
}
}
  1. Monitor cache effectiveness:
Terminal window
# Squid cache statistics
squidclient -h localhost mgr:info | grep -E "(Request|Hit|Memory)"
# Expected output for healthy cache:
# Request Hit Ratios: 5min: 35.2%, 60min: 42.1%
# Byte Hit Ratios: 5min: 28.4%, 60min: 38.7%
# Memory accesses per second: 45.2/sec

Phase 4: Application-specific optimisation

Different applications require specific optimisations. This section covers the primary bandwidth consumers in field office environments.

  1. Configure email for low-bandwidth operation. For Microsoft 365, apply these Outlook settings via Group Policy or Intune:
Cached Exchange Mode: Enabled
Download shared folders: Disabled
Download Public Folder Favorites: Disabled
Sync slider: 1 month (not "All")
Download full items: Headers only (then full item on selection)

For Outlook on Windows, registry settings:

Terminal window
# Download headers only for poor connections
$regPath = "HKCU:\Software\Microsoft\Office\16.0\Outlook\Cached Mode"
Set-ItemProperty -Path $regPath -Name "Download" -Value 1 -Type DWord
# Sync only 1 month
Set-ItemProperty -Path $regPath -Name "SyncWindowSetting" -Value 1 -Type DWord

Configure attachment size warnings:

Terminal window
# Warn on attachments over 5 MB
Set-ItemProperty -Path "HKCU:\Software\Microsoft\Office\16.0\Outlook\Preferences" `
-Name "MaximumAttachmentSize" -Value 5120 -Type DWord
  1. Configure cloud storage sync clients for bandwidth-constrained operation. For OneDrive:
Terminal window
# Limit upload bandwidth to 128 KB/s
Set-ItemProperty -Path "HKCU:\Software\Microsoft\OneDrive" `
-Name "UploadBandwidthLimit" -Value 128 -Type DWord
# Limit download bandwidth to 256 KB/s
Set-ItemProperty -Path "HKCU:\Software\Microsoft\OneDrive" `
-Name "DownloadBandwidthLimit" -Value 256 -Type DWord
# Enable Files On-Demand (download only when accessed)
Set-ItemProperty -Path "HKCU:\Software\Microsoft\OneDrive" `
-Name "FilesOnDemandEnabled" -Value 1 -Type DWord

For Google Drive, edit preferences via desktop application or deploy configuration:

// Preferences file location varies by OS
{
"bandwidth_rx_kbps": 256,
"bandwidth_tx_kbps": 128
}
  1. Configure video conferencing for low-bandwidth. Microsoft Teams:
Terminal window
# Teams bandwidth policies (via Teams Admin Center or PowerShell)
# Set via CsTeamsMeetingPolicy
Set-CsTeamsMeetingPolicy -Identity "LowBandwidthPolicy" `
-VideoBitRateKb 400 `
-MediaBitRateKb 1000
# Assign to users in low-bandwidth locations
Grant-CsTeamsMeetingPolicy -Identity "user@org.example" `
-PolicyName "LowBandwidthPolicy"

Client-side Teams settings (user must configure or deploy via template):

Settings > Privacy > Disable "Read receipts"
Settings > Notifications > Reduce notification frequency
Settings > General > Disable "Auto-start application"

For Zoom, configure via web portal or local policy:

Meeting Settings:
- HD video: Disabled
- Touch up my appearance: Disabled
- Virtual background: Disabled (requires encoding overhead)
- Group HD video: Disabled
Bandwidth recommendations:
- Audio only: 60-80 kbps
- Video (standard): 300-600 kbps
- Video (HD disabled): 150-300 kbps
  1. Configure web browsers to reduce bandwidth. Deploy these settings organisation-wide:
// Chrome policy
{
"DefaultImagesSetting": 2,
"ImagesAllowedForUrls": ["https://your-internal-apps.example/*"],
"BackgroundModeEnabled": false,
"MetricsReportingEnabled": false,
"SafeBrowsingExtendedReportingEnabled": false
}

The DefaultImagesSetting: 2 blocks images by default, with explicit allowlist for internal applications where images are necessary.

  1. Disable or limit telemetry and background services that consume bandwidth without user benefit:
Terminal window
# Windows telemetry reduction
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DataCollection" `
-Name "AllowTelemetry" -Value 0 -Type DWord
# Disable Customer Experience Improvement Program
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\SQMClient\Windows" `
-Name "CEIPEnable" -Value 0 -Type DWord
# Disable Windows Spotlight (downloads images)
Set-ItemProperty -Path "HKCU:\SOFTWARE\Policies\Microsoft\Windows\CloudContent" `
-Name "DisableWindowsSpotlightFeatures" -Value 1 -Type DWord

Phase 5: Image and media optimisation

Images and media constitute 50-70% of web traffic. Reducing image payload delivers substantial bandwidth savings.

  1. Configure Squid to recompress images on-the-fly using ICAP or eCAP. Install and configure an image optimisation service:
Terminal window
# Install image processing tools
sudo apt install imagemagick webp optipng jpegoptim
# Create optimisation script
cat > /usr/local/bin/optimize-image.sh << 'EOF'
#!/bin/bash
INPUT="$1"
OUTPUT="$2"
MIME=$(file -b --mime-type "$INPUT")
case "$MIME" in
image/jpeg)
jpegoptim --strip-all --max=70 -o "$OUTPUT" "$INPUT"
;;
image/png)
optipng -o2 -out "$OUTPUT" "$INPUT"
;;
image/webp)
cwebp -q 70 "$INPUT" -o "$OUTPUT"
;;
*)
cp "$INPUT" "$OUTPUT"
;;
esac
EOF
chmod +x /usr/local/bin/optimize-image.sh

For production deployment, use a dedicated ICAP server such as c-icap with GreasySpoon or commercial solutions.

  1. Deploy browser extensions that compress images before download. Privacy Badger and uBlock Origin also reduce tracking-related bandwidth. For managed deployment:
// Chrome ExtensionInstallForcelist policy
{
"ExtensionInstallForcelist": [
"cjpalhdlnbpafiamejdnhcphjbkeiagm;https://clients2.google.com/service/update2/crx"
]
}
  1. Configure content delivery to prefer efficient formats. Modern image formats (WebP, AVIF) are 25-35% smaller than JPEG at equivalent quality. Ensure Squid accepts and caches these formats:
# Accept modern formats
request_header_access Accept allow all
# Ensure Accept includes modern formats in requests

Phase 6: Update and patch scheduling

Software updates compete with operational traffic. Scheduling updates for off-peak hours and distributing load prevents bandwidth exhaustion during business hours.

  1. Configure Windows Update scheduling via Group Policy:
Computer Configuration > Administrative Templates > Windows Components > Windows Update
Configure Automatic Updates: Enabled
- Configure automatic updating: 4 - Auto download and schedule the install
- Scheduled install day: 0 - Every day
- Scheduled install time: 02:00
Specify intranet Microsoft update service location: Enabled
- [Point to local WSUS if available]
Turn off auto-restart for updates during active hours: Enabled
- Active hours start: 07:00
- Active hours end: 20:00
  1. Configure Linux update scheduling:
/etc/apt/apt.conf.d/10periodic
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Download-Upgradeable-Packages "1";
APT::Periodic::AutocleanInterval "7";
APT::Periodic::Unattended-Upgrade "1";
# /etc/apt/apt.conf.d/50unattended-upgrades
Unattended-Upgrade::Automatic-Reboot "false";
Unattended-Upgrade::Automatic-Reboot-Time "03:00";
# Bandwidth limiting during downloads
Acquire::http::Dl-Limit "100";
Acquire::https::Dl-Limit "100";
  1. Configure application update policies. For Microsoft 365:
<!-- Office Deployment Tool configuration.xml -->
<Configuration>
<Updates Enabled="TRUE"
UpdatePath="\\server\share\office"
TargetVersion="16.0.14326.20404"
Deadline="05/01/2024 18:00"/>
</Configuration>

Point UpdatePath to a local network share that syncs during off-hours, preventing each client from downloading updates individually.

  1. Create bandwidth reservation for essential updates using traffic control. Reserve 10% of bandwidth for security updates that must proceed regardless of congestion:
Terminal window
# Reserve bandwidth for update traffic to Microsoft/Canonical servers
# See Phase 7 for complete tc configuration

Phase 7: Quality of Service configuration

Quality of Service (QoS) prioritises traffic so critical applications function even when the link saturates. QoS does not increase bandwidth; it ensures available bandwidth serves the most important traffic first.

+------------------------------------------------------------------+
| QoS PRIORITY STRUCTURE |
+------------------------------------------------------------------+
| |
| Priority 1 (Strict) [ Voice/Video ] 20% guaranteed |
| +---------------------------------------------------------+ |
| | VoIP, Video conferencing (marked DSCP EF/AF41) | |
| +---------------------------------------------------------+ |
| |
| Priority 2 (High) [ Interactive ] 30% guaranteed |
| +---------------------------------------------------------+ |
| | Web apps, email client, SSH, RDP | |
| +---------------------------------------------------------+ |
| |
| Priority 3 (Normal) [ Business ] 30% guaranteed |
| +---------------------------------------------------------+ |
| | General web, file sync (throttled), messaging | |
| +---------------------------------------------------------+ |
| |
| Priority 4 (Low) [ Background ] 15% guaranteed |
| +---------------------------------------------------------+ |
| | Updates, backups, telemetry, large downloads | |
| +---------------------------------------------------------+ |
| |
| Priority 5 (Scavenger) [ Best effort ] 5% guaranteed |
| +---------------------------------------------------------+ |
| | All other traffic, unclassified | |
| +---------------------------------------------------------+ |
| |
| Note: Guarantees apply at saturation; unused bandwidth |
| is available to lower priorities |
+------------------------------------------------------------------+

Figure 2: QoS priority structure with bandwidth guarantees

  1. Identify the outbound interface and total bandwidth. All tc commands require these values:
Terminal window
# Identify interface
ip route | grep default
# Example output: default via 192.168.1.1 dev eth0
# Set bandwidth variable (in kbit)
INTERFACE="eth0"
BANDWIDTH="1024" # 1 Mbps in kbit
  1. Create the root queueing discipline and class hierarchy:
Terminal window
# Clear existing qdiscs
sudo tc qdisc del dev $INTERFACE root 2>/dev/null
# Create HTB root qdisc
sudo tc qdisc add dev $INTERFACE root handle 1: htb default 50
# Create root class at full bandwidth
sudo tc class add dev $INTERFACE parent 1: classid 1:1 htb \
rate ${BANDWIDTH}kbit ceil ${BANDWIDTH}kbit
# Priority 1: Voice/Video - 20% guaranteed, can burst to 40%
sudo tc class add dev $INTERFACE parent 1:1 classid 1:10 htb \
rate $((BANDWIDTH * 20 / 100))kbit \
ceil $((BANDWIDTH * 40 / 100))kbit \
prio 1
# Priority 2: Interactive - 30% guaranteed, can burst to 50%
sudo tc class add dev $INTERFACE parent 1:1 classid 1:20 htb \
rate $((BANDWIDTH * 30 / 100))kbit \
ceil $((BANDWIDTH * 50 / 100))kbit \
prio 2
# Priority 3: Business - 30% guaranteed, can burst to 60%
sudo tc class add dev $INTERFACE parent 1:1 classid 1:30 htb \
rate $((BANDWIDTH * 30 / 100))kbit \
ceil $((BANDWIDTH * 60 / 100))kbit \
prio 3
# Priority 4: Background - 15% guaranteed, can burst to 40%
sudo tc class add dev $INTERFACE parent 1:1 classid 1:40 htb \
rate $((BANDWIDTH * 15 / 100))kbit \
ceil $((BANDWIDTH * 40 / 100))kbit \
prio 4
# Priority 5: Scavenger (default) - 5% guaranteed, can burst to 30%
sudo tc class add dev $INTERFACE parent 1:1 classid 1:50 htb \
rate $((BANDWIDTH * 5 / 100))kbit \
ceil $((BANDWIDTH * 30 / 100))kbit \
prio 5
# Add stochastic fairness to each class
sudo tc qdisc add dev $INTERFACE parent 1:10 handle 10: sfq perturb 10
sudo tc qdisc add dev $INTERFACE parent 1:20 handle 20: sfq perturb 10
sudo tc qdisc add dev $INTERFACE parent 1:30 handle 30: sfq perturb 10
sudo tc qdisc add dev $INTERFACE parent 1:40 handle 40: sfq perturb 10
sudo tc qdisc add dev $INTERFACE parent 1:50 handle 50: sfq perturb 10
  1. Create filters to classify traffic into appropriate classes:
Terminal window
# Voice/Video: DSCP EF (46) and AF41 (34)
sudo tc filter add dev $INTERFACE parent 1: protocol ip prio 1 \
u32 match ip tos 0xb8 0xfc flowid 1:10
sudo tc filter add dev $INTERFACE parent 1: protocol ip prio 1 \
u32 match ip tos 0x88 0xfc flowid 1:10
# Teams/Zoom ports (UDP high ports for media)
sudo tc filter add dev $INTERFACE parent 1: protocol ip prio 1 \
u32 match ip protocol 17 0xff \
match ip dport 3478 0xffff flowid 1:10
sudo tc filter add dev $INTERFACE parent 1: protocol ip prio 1 \
u32 match ip protocol 17 0xff \
match ip dport 50000 0xfff0 flowid 1:10
# Interactive: SSH, RDP
sudo tc filter add dev $INTERFACE parent 1: protocol ip prio 2 \
u32 match ip dport 22 0xffff flowid 1:20
sudo tc filter add dev $INTERFACE parent 1: protocol ip prio 2 \
u32 match ip dport 3389 0xffff flowid 1:20
# Interactive: HTTPS (general web)
sudo tc filter add dev $INTERFACE parent 1: protocol ip prio 3 \
u32 match ip dport 443 0xffff flowid 1:20
# Background: Common update ports and large transfers
# Microsoft Update
sudo tc filter add dev $INTERFACE parent 1: protocol ip prio 4 \
u32 match ip dst 13.107.4.50/32 flowid 1:40
# Ubuntu archive
sudo tc filter add dev $INTERFACE parent 1: protocol ip prio 4 \
u32 match ip dst 91.189.88.0/24 flowid 1:40
  1. Persist the configuration across reboots:
# Create script
cat > /etc/network/if-up.d/qos-setup << 'EOF'
#!/bin/bash
# QoS configuration for low-bandwidth optimisation
# Applied on interface up
INTERFACE="eth0"
BANDWIDTH="1024"
[Insert all tc commands from above]
EOF
chmod +x /etc/network/if-up.d/qos-setup
  1. Verify QoS is active and classifying traffic:
Terminal window
# Show class statistics
tc -s class show dev eth0
# Expected output shows packets in each class
# class htb 1:10 rate 204Kbit ceil 409Kbit
# Sent 145234 bytes 892 pkt (dropped 0, overlimits 12...)

Phase 8: User guidance deployment

Technical optimisation provides only part of the solution. User behaviour determines 30-50% of bandwidth consumption. Deploy clear guidance that helps users operate effectively without detailed technical knowledge.

  1. Create a quick reference card for low-bandwidth operation:
WORKING ON SLOW CONNECTIONS - QUICK GUIDE
EMAIL
✓ Send files via SharePoint/Drive link, not attachment
✓ Keep attachments under 5 MB
✓ Check mail manually instead of auto-refresh
VIDEO CALLS
✓ Turn camera off unless essential
✓ Use phone audio if video quality poor
✓ Close other apps during calls
✓ Join 5 minutes early to let connection stabilise
FILES
✓ Use "Available offline" only for files you need
✓ Don't sync entire folders, select specific files
✓ Download large files outside work hours
WEB
✓ Close unused browser tabs
✓ Disable auto-play videos
✓ Use Reader View for articles
REPORT PROBLEMS
Contact IT if connection unusable for >30 minutes
  1. Configure default behaviours that enforce good practice without user action. The technical configurations in previous phases accomplish this, but ensure users understand why things behave differently than in high-bandwidth offices:
WHAT'S DIFFERENT HERE
- Email downloads headers first, full message when you open it
- Images may not load automatically on websites
- Large file uploads happen in background, may take hours
- Video calls default to audio-only, enable video manually
- Software updates happen overnight, don't shut down computer
These settings save bandwidth so everyone can work.
  1. Establish a feedback mechanism so users can report when optimisation causes problems with specific applications or workflows. Not all workflows are anticipated; user feedback identifies necessary exceptions.

Phase 9: Monitoring configuration

Ongoing monitoring validates that optimisations remain effective and identifies emerging bandwidth pressures.

  1. Configure vnstat for long-term traffic analysis:
Terminal window
# Ensure vnstat daemon runs
sudo systemctl enable vnstat
sudo systemctl start vnstat
# Verify data collection
vnstat -l -i eth0
# Shows live traffic for verification
  1. Create daily bandwidth report:
/etc/cron.daily/bandwidth-report
#!/bin/bash
REPORT="/var/log/bandwidth/daily-$(date +%Y%m%d).txt"
mkdir -p /var/log/bandwidth
echo "Bandwidth Report - $(date)" > $REPORT
echo "================================" >> $REPORT
echo "" >> $REPORT
echo "Daily Summary:" >> $REPORT
vnstat -d -i eth0 | tail -15 >> $REPORT
echo "" >> $REPORT
echo "Hourly Detail:" >> $REPORT
vnstat -h -i eth0 >> $REPORT
echo "" >> $REPORT
echo "Cache Statistics:" >> $REPORT
squidclient mgr:info | grep -E "(Hit|Request)" >> $REPORT
# Email report if mail configured
# mail -s "Daily Bandwidth Report" it@example.org < $REPORT
  1. Set up alerting for bandwidth exhaustion:
# Simple threshold check (add to cron.hourly)
#!/bin/bash
THRESHOLD=90 # Alert at 90% utilisation
BANDWIDTH_KBPS=1024
# Get current 5-minute average in KB/s
CURRENT=$(vnstat -tr 300 -i eth0 | grep "rx" | awk '{print $2}')
CURRENT_KBPS=$((CURRENT * 8))
UTILISATION=$((CURRENT_KBPS * 100 / BANDWIDTH_KBPS))
if [ $UTILISATION -gt $THRESHOLD ]; then
logger -p user.warning "Bandwidth utilisation at ${UTILISATION}%"
# Add email/SMS alert as appropriate
fi
  1. Monitor QoS class distribution to verify traffic classification:
Terminal window
# Add to monitoring
tc -s class show dev eth0 | grep -E "(class|Sent)" > /var/log/qos-stats.log

Verification

After completing all phases, verify the optimisation achieves target outcomes.

Run bandwidth comparison during peak hours:

Terminal window
# Measure current consumption (after optimisation)
vnstat -l -i eth0 -s 300
# Compare to baseline recorded before optimisation
# Target: 40-70% reduction in peak bandwidth consumption

Verify cache hit rate:

Terminal window
squidclient -h localhost mgr:info | grep "Request Hit Ratios"
# Target: >30% hit rate after 1 week of operation
# Target: >40% hit rate after 1 month

Confirm QoS prioritisation under load:

Terminal window
# Generate test load
iperf3 -c speedtest.example -t 60 &
# During load, verify voice traffic still prioritised
tc -s class show dev eth0 | grep -A2 "1:10"
# Class 1:10 should show minimal drops

Test application performance:

Terminal window
# Measure page load time
curl -o /dev/null -s -w "%{time_total}\n" https://mail.example.org
# Target: <10 seconds for primary applications
# Compare to baseline (often >30 seconds pre-optimisation)

Verify user experience:

Criteria Target
Email check (open Outlook) <30 seconds to usable
Web application login <20 seconds
File open from SharePoint <60 seconds for 1 MB file
Video call join <45 seconds to connected

Troubleshooting

SymptomCauseResolution
No bandwidth improvement visibleCache not intercepting trafficVerify proxy configuration; check browser proxy settings; confirm WPAD or PAC file deployed
Cache hit rate below 20% after 2 weeksInsufficient cache size or aggressive cache-busting headersIncrease cache_dir size; review refresh_pattern rules; check for Cache-Control: no-store headers
Video calls still poor despite QoSTraffic not matching QoS filters; DSCP marks strippedVerify filters with tc filter show; check if upstream ISP preserves DSCP; use port-based classification
Single user consuming all bandwidthNo per-user limits configuredAdd Squid delay pools for per-IP limiting; configure per-user QoS classes
Applications broken after image blockingRequired images blockedAdd domain to ImagesAllowedForUrls policy; review application requirements
Updates downloading during work hoursScheduled time incorrect or override triggeredVerify Windows Update GPO; check for manual “Check for updates” by users; review WSUS approval timing
QoS rules not surviving rebootScript not executing on interface upVerify script in /etc/network/if-up.d/ has execute permission; check script runs manually
Squid consuming excessive CPUSSL bump decryption overhead on underpowered hardwareExclude trusted domains from SSL bump; upgrade proxy hardware; consider dedicated proxy appliance
DNS queries slow despite local cacheDNS cache not being usedVerify clients point to local DNS; check DHCP providing correct DNS server
vnstat showing no dataInterface not initialised in vnstat databaseRun vnstat -u -i eth0; restart vnstat service
Compression making some sites failDouble compression or incompatible contentAdd problematic domains to compression exclusion list; disable compression for specific MIME types
Users complaining about “everything is slow”Expectations not managed; actual problem not bandwidthRun speed test to verify link; check for issues beyond bandwidth (latency, packet loss); compare to baseline

Iterative tuning

Low-bandwidth optimisation requires ongoing adjustment. Review cache statistics weekly for the first month, then monthly. Adjust QoS class allocations based on observed traffic patterns. A well-tuned configuration at deployment becomes suboptimal as application usage evolves.

Automation

Save the complete configuration as deployable scripts:

/opt/bandwidth-optimisation/deploy.sh
#!/bin/bash
set -e
INTERFACE="${1:-eth0}"
BANDWIDTH="${2:-1024}"
echo "Deploying bandwidth optimisation for $INTERFACE at ${BANDWIDTH}kbit"
# Deploy Squid configuration
cp squid.conf /etc/squid/squid.conf
systemctl restart squid
# Deploy QoS rules
./qos-setup.sh $INTERFACE $BANDWIDTH
# Deploy monitoring
cp bandwidth-report /etc/cron.daily/
chmod +x /etc/cron.daily/bandwidth-report
echo "Deployment complete. Verify with: tc -s class show dev $INTERFACE"

For Windows endpoints, package Group Policy preferences as a GPO backup importable to any domain:

Terminal window
# Export current policies after configuration
Backup-GPO -Name "Low Bandwidth Optimisation" -Path "\\server\share\gpo-backups"
# Import at new location
Import-GPO -BackupGpoName "Low Bandwidth Optimisation" `
-Path "\\server\share\gpo-backups" `
-TargetName "Low Bandwidth Optimisation" `
-CreateIfNeeded

See also