• Skip to primary navigation
  • Skip to main content
Ethan Banks

Ethan Banks

@ecbanks

  • Blog
  • Book
  • Podcasts
  • RSS
  • Show Search
Hide Search

How To: Simple Juniper SRX Rate-Limiting via Policer

Ethan Banks · 4 minutes to read
Published April 11, 2014 · Updated April 11, 2014

I recently needed to configure rate-limiting on a Juniper SRX650 firewall’s 1GbE interface facing an ISP. The scenario was that the ISP allowed line rate traffic and billed at the 95th percentile of utilization. As long as 95th percentile was under the number of bps we were paying for, there was no excess charge. But that possibility of an excess charge was sort of annoying. How to provide ease of mind? Rate limit all traffic going through the 1GbE interfaces to the ISP.

In Juniper-land, there are several different ways to accomplish QoS tasks like this. I opted to run a simple policer in the end, but I took the following notes along the way.

  • Some features & functions vary by hardware interface. IOW, not all QoS capability is necessarily going to work everywhere across every Junos device or interface. This isn’t shocking. To perform QoS functions at scale (i.e. a useful bits-per-second rate), there is a reliance on silicon. Not all Juniper devices or line cards in those devices have the same ASICs. Therefore, not all QoS functionality will be identical. This is exactly what you find with other vendors.
  • Similar to Cisco hierarchical QoS, it’s possible to build complex Junos QoS policies using the “class-of-service” command hierarchy. Digging through this documentation, a network engineer creates forwarding-classes & schedulers that are called by scheduler-maps. Scheduler-maps are applied to interfaces. This is similar to Cisco MQC behavior where class-maps are called by policy-maps, and policy-maps are applied to interfaces.
  • I didn’t dig into class-of-service too deeply, but it appears to forward based on the CoS bits in 802.1q tagged frames. I need to dig a bit more to see if “class-of-service” also copes with DSCP values, which is the 6-bit value contained in the IP ToS byte. Most network-wide QoS schemes, expect to make queuing decisions on DSCP values at some junctions, and not merely CoS.
  • I’m still struggling to navigate Juniper’s documentation hierarchy as effectively as I would like. I’ve found the greatest success not with Google, but in Juniper’s Configuration Guide PDFs. I’ve downloaded a pile of them, and they are more likely to teach me what I need. The more I refer to these PDFs, the more familiar I’m getting with the Juniper way of looking at the world.

Here’s the solution I ended up with on a SRX650 cluster running 11.4 family code. This was verified to work via a simple bandwidth speed testing site, where the results went from 1Gbps line rate down to the policed rate in both directions. Sadly. ;-)

Commented Code

# Create the policer. In this case, we’re at 80Mbps, and
# allowing a data burst of 625KB (that’s a byte count, not
# a data rate). Why 625KB? That’s the amount of data that
# can flow through a 1GbE interface in 5ms, the burst
# minimum recommended by Juniper here. We can make the burst
# value bigger if we choose.
#
# Creating the policer by itself does nothing. The policer
# must be called elsewhere in the policy to be effective.
#
set firewall policer GLOBAL-POLICER if-exceeding bandwidth-limit 80m
set firewall policer GLOBAL-POLICER if-exceeding burst-size-limit 625k
set firewall policer GLOBAL-POLICER then discard
#
# Create the outbound filter. We could create just one filter
# and apply it both inbound and outbound, but this gives us a
# little more flexibility, and makes certain that reporting
# via “show firewall filter” is not ambiguous.
#
# The filter says that traffic matching anything is subject to
# the policer we created above. For completeness, I added a
# “END-POLICY” term that allows any traffic that falls through
# from the “SOURCE-ANY” to pass through the filter. Technically,
# this shouldn't be required, but it’s a fail-safe as firewall
# filters *will* drop traffic if not configured correctly. This
# is similar to putting a “permit ip any any” at the end of a
# Cisco ACL.
#
set firewall filter OUTBOUND-FILTER term SOURCE-ANY from source-address 0.0.0.0/0
set firewall filter OUTBOUND-FILTER term SOURCE-ANY then policer GLOBAL-POLICER
set firewall filter OUTBOUND-FILTER term SOURCE-ANY then accept
set firewall filter OUTBOUND-FILTER term END-POLICY then accept
#
# Create inbound filter.
#
set firewall filter INBOUND-FILTER term SOURCE-ANY from source-address 0.0.0.0/0
set firewall filter INBOUND-FILTER term SOURCE-ANY then policer GLOBAL-POLICER
set firewall filter INBOUND-FILTER term SOURCE-ANY then accept
set firewall filter INBOUND-FILTER term END-POLICY then accept
#
# Apply the inbound and outbound filter to the appropriate
# interface. In the case of a clustered SRX, we’re applying
# the filter to the redundant Ethernet interface uplinking to
# the ISP.
#
set interfaces reth-0 unit 0 family inet filter input INBOUND-FILTER
set interfaces reth-0 unit 0 family inet filter output OUTBOUND-FILTER

To see what’s happening with the policy, try…

# Display what filters are applied.
show interfaces reth0 detail | match "(interface|filter)”
#
# I believe this displays the number of packets dropped
# as a result of the filter? Docs are vague.
show firewall filter INBOUND-FILTER
show firewall filter OUTBOUND-FILTER

Resulting Configuration

interfaces {
    reth0 {
        redundant-ether-options {
            redundancy-group 1;
        }
        unit 0 {
            family inet {
                filter {
                    input INBOUND-FILTER;
                    output OUTBOUND-FILTER;
                }
                address 10.20.30.40/24;
            }
        }
    }
firewall {
    policer GLOBAL-POLICER {
        if-exceeding {
            bandwidth-limit 80m;
            burst-size-limit 625k;
        }
        then discard;
    }
    filter OUTBOUND-FILTER {
        term SOURCE-ANY {
            from {
                source-address {
                    0.0.0.0/0;
                }
            }
            then {
                policer GLOBAL-POLICER;
                accept;
            }
        }
        term END-POLICY {
            then accept;
        }
    }
    filter INBOUND-FILTER {
        term SOURCE-ANY {
            from {
                source-address {
                    0.0.0.0/0;
                }
            }
            then {
                policer GLOBAL-POLICER;
                accept;
            }
        }
        term END-POLICY {
            then accept;
        }
    }
}

I might test some of the other techniques that I think would work for this, but need to get Firefly running in my lab first. Why bother? The downside of policing is that it’s not especially elegant. Global policers are a pretty large hammer. While this was straightforward to implement, posed (in my estimation) the least amount of implementation risk to my production firewalls, and addressed the issue head on, a more elegant QoS approach is a modular one.

It’s worth pointing out that the firewall filters above can have additional terms added to them to allow for more granular treatment of which IP addresses are getting policed. Even so, a true QoS policy would break down traffic classes in a hierarchical manner that would allow for maximum policy flexibility without having to rewrite the entire policy each time a significant change was required. This is something I need to evaluate anyway, as using SRX devices at the edge of my far-flung network is a topic of interest.

Filed Under: Hands OnPublished on ethancbanks.com.

Have You Read…?

  1. What Does An ‘R’ Before A String Mean In Python?
  2. How To Pass API Query Parameters In A Curl Request
  3. Synology Running Out Of Space? Empty The Recycle Bin.
  4. Free Networking Lab Images From Arista, Cisco, nVidia (Cumulus)
  5. How To Create A Python Function You Can Call From Other Scripts
  6. How To Use Grep + Regex To Match Non-200 HTTP Status Codes In Apache Server Logs
  7. When Stretching Layer Two, Separate Your Fate
  8. How To: Simple Juniper SRX Rate-Limiting via Policer
  9. Using AppleScript To Size A Window To 16×9 On MacOS
  10. Auto-Adding Routes When Mac PPTP Connection Comes Up

MORE FREE STUFF!

Check out my IT Education Twitter Collection.
Curated tweets for IT professionals trying to up their game.

twitter mastodon linkedin instagram linkedin

Have a great day. You're doing an outstanding job. 👍

About · Privacy

Copyright © 2007–2023 Ethan Banks