How To: Simple Juniper SRX Rate-Limiting via Policer

H

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.

7 comments

  • 1) If someone throws high volume UDP at you, and you discard, will the ISP still charge you for the BW used?
    2) If you want a really quick and dirty limiter, you can skip the firewall filters and apply the policers directly to the interface
    3) (For outbound traffic only) These kinds of policers don’t really play nice with some types of traffic. I usually prefer rate limiting instead of policing/discarding. You can do rate limiting with schedulers, but on the branch boxes (SRX650 is the biggest branch box) you have something called virtual channels that works well and are not that hard to set up. I can set up an example if you like.

    /Per

    • 1) Interesting question. We haven’t faced that scenario, so I’m not sure. But I do know we have a good enough relationship with them that I think they’d work with us to assist with that sort of an attack and help mitigate. I don’t think they’d bill us just to bill us in a situation where it would be beyond our control to throttle.

      2) Very fair point in the way I positioned the solution I wrote up, although in the digging about I did, that specific approach didn’t work consistently for folks. That’s part of the reason I shied away. That, and it truly gives you zero options for granularity. The firewall filter approach at least lets you apply different policers to different IP networks if you want. I have a near-term use case for that (where I’ll add terms other than simply 0.0.0.0/0), so opted to go that way.

      3) Rate limiting vs. policing was something I could not find good Juniper documentation on. I’m familiar with shaping vs. policing from the Cisco world where the nature of how bursting is handled and the token bucket replenished is something I understand. I just didn’t land on the right documentation describing this in Juniper-speak. Any pointers on this would be welcome, as I completely agree – shaping outbound traffic is the way to go. Nice, even traffic graphs are the result in my experience – fewer retransmissions in TCP flows. And yes, I’m running an SRX650 cluster, so I would very much appreciate the example of virtual channels. I don’t remember running into those at all in Juniper docs I hit, but will search on them. If you care to send me code example, feel free to use ethan.banks@packetpushers.net. I want to blog on this topic more, so I’ll do my best not to waste your efforts! :-)

      • Answer (soon) via direct mail, feel free to excerpt any interesting parts and post,

        /Per
        Twittter: @PerWesterlund

  • hey Ethan, Thanks for this , Can we create a filter for that can count the number of bytes and drops once the bandwidth limit is reached

    We have ISP who is charging on data rate i.e 800Gbps and more than this Internat usage is chargeable. Now i need to design a filter should drop that traffic after 800 Gbps , So that we can announce the network from other non-commited internet link.

By Ethan Banks

Ethan Banks is a podcaster and writer with a BSCS and 20+ years in enterprise IT. He's operated data centers with a special focus on infrastructure — especially networking. He's been a CNE, MCSE, CEH, CCNA, CCNP, CCSP, and CCIE R&S #20655. He's the co-founder of Packet Pushers Interactive, LLC where he creates content for humans in the hot aisle.

Newsletter