Skip to content

Router Configuration

Replace 192.0.2.100 with the actual IP of your flowwler server throughout.


Flow input comparison

The flow-export mechanisms below differ in two ways that matter for DDoS detection: whether they carry per-packet length data, and how long traffic takes to reach flowwler after it crosses the router. Pick a row before configuring a specific vendor.

Input Packet-length data Export / detection latency Sampling rate source
NetFlow v5 (MikroTik) Not available — fixed 12-tuple record has no length field Flow-cache based: bound by the router's active/inactive-flow timeout (MikroTik default: 1m active / 15s inactive) Encoded in the packet header, bits 22–24 — but MikroTik RouterOS has no statistical sampling at all, so this is always 1:1; default_sampling_rate must be left unset (see the MikroTik note below)
NetFlow v9 / IPFIX, standard templates (Cisco IOS-XR, Juniper inline-jflow) Only if the exporter's template carries fields 25/26 (MIN_PKT_LNGTH/MAX_PKT_LNGTH) — the vendor-default templates configured below (Juniper's built-in ipv4-template, Cisco's record ipv4) do not include them Flow-cache based: bound by the cache's active/inactive timeout, which is set per template/exporter, not fixed by the protocol. The Juniper example below sets flow-active-timeout 10/flow-inactive-timeout 10 explicitly; the Cisco IOS-XR example does not set a cache timeout at all, so it inherits the platform default (commonly 30 min active / 15s inactive) — add an explicit cache timeout to get comparable detection latency Options Data record (setID 1/3, JunOS only); otherwise the configured default_sampling_rate
IPFIX inline monitoring (Junos, MX/PTX) Yes — decoded from the captured frame's own IP header (fields 312/315) Near real time — no flow cache, one export per sampled packet; the practical latency floor is flowwler's aggregation_window (3–5s). Trade-off: export volume now scales with sampled packets-per-second rather than active flow count, so it costs more collector-facing bandwidth than cache-based NetFlow/IPFIX at the same sampling rate sampling-rate on the inline-monitoring instance. treat_no_output_as_discard has also been observed to work here — see the note in the IPFIX inline monitoring section — but confirm your own router's template carries field 14 (OUTPUT_SNMP) before relying on it
sFlow v5 (Arista EOS) Not available — frame_length scales Bytes/Packets but is never exposed as a per-source min/max Near real time — flow samples are generated per sampled packet, not on a timer, so latency is the same per-packet-PPS trade-off as inline monitoring above. Arista's polling-interval (5s in the example below) only governs periodic interface counter samples — it does not delay flow samples Per-sample sampling_rate field, falls back to default_sampling_rate

Packet-length data (where available) feeds FlowSpec type-10 NLRI matching and attacker source selection — see PktLenRange for exact semantics and the same exporter breakdown from that angle.


Flow Export

Juniper JunOS

Standard IPFIX with inline-jflow

This configuration uses inline-jflow with IPFIX (version-ipfix) and a named sampling instance — the recommended approach for MX series routers. Inline-jflow runs sampling in hardware on the FPC, which avoids punting sampled packets to the Routing Engine.

Enable sampling on each transit and peering interface. JunOS needs sampling for both IPv4 and IPv6 in both directions:

set interfaces ge-0/0/0 unit 0 family inet  sampling input
set interfaces ge-0/0/0 unit 0 family inet  sampling output
set interfaces ge-0/0/0 unit 0 family inet6 sampling input
set interfaces ge-0/0/0 unit 0 family inet6 sampling output
services {
    flow-monitoring {
        version-ipfix {
            template TPL-V4 {
                flow-active-timeout 10;       /* export active flows every 10 s - fast attack detection */
                flow-inactive-timeout 10;     /* export idle flows after 10 s */
                template-refresh-rate {
                    packets 1000;
                    seconds 30;
                }
                option-refresh-rate {         /* re-sends sampling-rate option template */
                    packets 1000;
                    seconds 30;
                }
                ipv4-template;               /* built-in template: IP headers + transport headers + sampling rate */
            }
            template TPL-V6 {
                flow-active-timeout 10;
                flow-inactive-timeout 10;
                template-refresh-rate {
                    packets 1000;
                    seconds 30;
                }
                option-refresh-rate {
                    packets 1000;
                    seconds 30;
                }
                ipv6-template;
            }
        }
    }
}
forwarding-options {
    sampling {
        instance {
            SAMPLING-INSTANCE {
                family inet {
                    input {
                        rate 1000;           /* 1:1000 sampling - adjust to match your traffic volume */
                    }
                    output {
                        flow-server 192.0.2.100 {    /* flowwler server IP */
                            port 2055;
                            version-ipfix {
                                template TPL-V4;
                            }
                        }
                        inline-jflow {
                            source-address 192.0.2.1; /* router loopback - used as the exporter IP in flowwler */
                        }
                    }
                }
                family inet6 {
                    input {
                        rate 1000;
                    }
                    output {
                        flow-server 192.0.2.100 {
                            port 2055;
                            version-ipfix {
                                template TPL-V6;
                            }
                        }
                        inline-jflow {
                            source-address 192.0.2.1;
                        }
                    }
                }
            }
        }
    }
}
chassis {
    fpc 0 {                     /* repeat for every FPC that handles transit traffic */
        pic 0 {
            sampling-instance SAMPLING-INSTANCE;
            inline-services {
                report-zero-oif-gw-on-discard; /* export flows with output ifIndex 0 when the router discards them
                                                  required for flowwler's treat_no_output_as_discard and
                                                  mitigation effectiveness metrics to work correctly */
                flow-table-size {
                    flex-flow-sizing;          /* auto-sizes the flow table based on observed traffic volume */
                    ipv6-extended-attrib;      /* enables full IPv6 5-tuple in the flow cache */
                }
            }
        }
    }
}

flowwler config to match:

netflow:
  treat_no_output_as_discard: true  # relies on report-zero-oif-gw-on-discard above
  # default_sampling_rate is not needed - the option template carries the rate automatically

Note: report-zero-oif-gw-on-discard causes JunOS to export flows for packets discarded by firewall filters or routing policy (output ifIndex = 0). flowwler uses these flows to compute the discard BPS/PPS metrics that indicate how much attack traffic is being dropped and to measure mitigation effectiveness. Without this option, discarded traffic is invisible to flowwler.

flex-flow-sizing (JunOS 15.1F7+) lets the FPC auto-size the flow cache based on observed traffic volume. If your JunOS version does not support it, remove the line and size flow-table-size manually.

IPFIX inline monitoring (MX/PTX, aggregation-free)

This alternative uses JunOS inline-monitoring services to ship truncated raw packet headers directly inside IPFIX frames — similar in spirit to sFlow, but transported in IPFIX. There is no flow cache and no export delay; attack detection time can be reduced to a few seconds. Use this on MX and PTX platforms when the lowest possible detection latency matters more than flow-level aggregation.

The sampling rate and collector are defined on the inline-monitoring instance. Traffic is steered into the instance via firewall filter — not via sampling input/output on the interface.

services {
    inline-monitoring {
        template INLINE-TPL {                        /* single template covers both IPv4 and IPv6 */
            template-refresh-rate 30;
            option-template-refresh-rate 100;
            observation-domain-id 1;
        }
        instance INLINE-INSTANCE {
            template-name INLINE-TPL;
            maximum-clip-length 126;                 /* bytes of packet header captured per sample */
            collector FLOWWLER {
                source-address 192.0.2.1;            /* router loopback - used as the exporter IP in flowwler */
                destination-address 192.0.2.100;     /* flowwler server IP */
                destination-port 2055;
                sampling-rate 1000;                  /* 1:1000 - adjust to match your traffic volume */
            }
        }
    }
}
firewall {
    family inet {
        filter INLINE-FILTER-V4 {
            term 1 {
                then {
                    inline-monitoring-instance INLINE-INSTANCE;
                    accept;
                }
            }
        }
    }
    family inet6 {
        filter INLINE-FILTER-V6 {                    /* IPv6 requires a separate filter */
            term 1 {
                then {
                    inline-monitoring-instance INLINE-INSTANCE;
                    accept;
                }
            }
        }
    }
}

Apply the filters to each transit and peering interface:

set interfaces ge-0/0/0 unit 0 family inet  filter input  INLINE-FILTER-V4
set interfaces ge-0/0/0 unit 0 family inet  filter output INLINE-FILTER-V4
set interfaces ge-0/0/0 unit 0 family inet6 filter input  INLINE-FILTER-V6
set interfaces ge-0/0/0 unit 0 family inet6 filter output INLINE-FILTER-V6

No special flowwler config is required — IPFIX frames arrive on the same port (2055) as standard IPFIX.

Note: Because there is no flow aggregation, flowwler's aggregation_window drives detection latency directly. Values of 3–5 seconds are practical with this export method and will produce accurate rate estimates without the cache-timeout delay inherent to standard inline-jflow.

Note: treat_no_output_as_discard does work with this mode on MX/PTX platforms observed so far — Junos annotates the same FPC-resolved egress interface (OUTPUT_SNMP, field 14) onto inline-monitoring records as it does for standard flow-cache exports, since both are sampled at the same hardware stage. Confirm your own template actually carries field 14 before relying on it: capture a live sample and check with go run ./tools/pcap_decode --verbose, or look for "field_type_ids" containing 14 in flowwler's debug logs when a template is first stored. If the field is present, set treat_no_output_as_discard: true under netflow: to get discard/effectiveness metrics for inline-monitoring victims exactly as you would with inline-jflow.

Cisco IOS-XR

flow exporter FLOWWLER
 destination 192.0.2.100
 source Loopback0
 transport udp 2055
 version 9
!
flow monitor IPV4-MONITOR
 exporter FLOWWLER
 record ipv4
!
flow monitor IPV6-MONITOR
 exporter FLOWWLER
 record ipv6
!
sampler SAMPLER-1000
 random 1 out-of 1000
!
interface GigabitEthernet0/0/0   /* repeat for all transit/peering interfaces */
 flow ipv4 monitor IPV4-MONITOR sampler SAMPLER-1000 ingress
 flow ipv6 monitor IPV6-MONITOR sampler SAMPLER-1000 ingress
!

Note: This example does not set a cache timeout, so the flow monitor uses your IOS-XR release's platform default — commonly 30 minutes active / 15 seconds inactive, far slower than the 10s used in the Juniper example above. Configure an explicit active/inactive cache timeout on the flow monitor if faster detection matters (see the flow input comparison table); the exact command syntax varies by IOS-XR release.

Arista EOS

sflow sample 1000
sflow polling-interval 5
sflow destination 192.0.2.100
sflow source-interface Loopback0
sflow run
!

Sampling is active on all interfaces by default once sflow run is set — no per-interface sflow enable is needed. To exclude an interface, disable it explicitly:

interface Ethernet1
   no sflow enable
!

Note: Arista EOS exports sFlow, not NetFlow. Configure the flowwler sflow: listener (default port 6343). Set default_sampling_rate in the flowwler sFlow config to match the value configured above (e.g. 1000).

MikroTik RouterOS

/ip traffic-flow
set enabled=yes interfaces=all cache-entries=4k active-flow-timeout=1m inactive-flow-timeout=15s

/ip traffic-flow target
add dst-address=192.0.2.100 port=2055 version=9

Note: MikroTik RouterOS v6/v7 exports NetFlow v5 or v9 from a single interface. The interfaces=all setting captures traffic on all interfaces. The sampling rate is always 1:1 (every packet is counted) - do not set default_sampling_rate in flowwler unless you have configured a different rate.


BGP

Juniper JunOS

protocols {
    bgp {
        group FLOWWLER {
            type external;
            multihop {
                ttl 5;
            }
            import FLOWWLER-IMPORT;
            export REJECT;
            remove-private;
            neighbor 192.0.2.100 {
                local-address 192.0.2.1;
                family inet {
                    unicast;
                    flow;
                }
                family inet6 {
                    unicast;
                    flow;
                }
                peer-as 65535;
            }
        }
    }
}
policy-options {
    policy-statement FLOWWLER-IMPORT {
        term BLACKHOLE-V4 {
            from {
                community BLACKHOLE;
                route-filter 0.0.0.0/0 prefix-length-range /32-/32;  /* only accept host routes - prevents accidental aggregate blackholing */
            }
            then {
                next-hop discard;
                accept;
            }
        }
        term BLACKHOLE-V6 {
            from {
                community BLACKHOLE;
                route-filter ::/0 prefix-length-range /128-/128;
            }
            then {
                next-hop discard;
                accept;
            }
        }
        term FLOWSPEC-V4 {
            from rib inetflow.0;        /* accept all IPv4 FlowSpec rules */
            then accept;
        }
        term FLOWSPEC-V6 {
            from rib inet6flow.0;       /* accept all IPv6 FlowSpec rules */
            then accept;
        }
        then reject;
    }
    community BLACKHOLE members 65535:666;
}

Cisco IOS-XR

router bgp 65001
 neighbor 192.0.2.100
  remote-as 65000
  address-family ipv4 unicast
   route-policy PERMIT-ALL in
  !
  address-family ipv4 flowspec
  !
  address-family ipv6 unicast
  !
  address-family ipv6 flowspec
  !
 !
!
flowspec
 address-family ipv4
  local-install interface-all
 !
 address-family ipv6
  local-install interface-all
 !
!

Arista EOS

router bgp 65001
   neighbor 192.0.2.100 remote-as 65000
   neighbor 192.0.2.100 maximum-routes 1000
   !
   address-family ipv4
      neighbor 192.0.2.100 activate
   !
   address-family ipv6
      neighbor 192.0.2.100 activate
   !
   address-family flow-spec ipv4
      neighbor 192.0.2.100 activate
   !
   address-family flow-spec ipv6
      neighbor 192.0.2.100 activate
   !
!
ip community-list standard BLACKHOLE permit 65535:666
!
route-map FLOWWLER-IN permit 10
   match community BLACKHOLE
   set ip next-hop 192.0.2.254   /* your discard/null next-hop */
!
route-map FLOWWLER-IN permit 20
!

MikroTik RouterOS

/routing bgp peer
add name=flowwler remote-address=192.0.2.100 remote-as=65000 \
    address-families=ip,ipv6 ttl=default

Note: MikroTik RouterOS has no native FlowSpec support. Only unicast blackhole routes (RTBH) are accepted. FlowSpec mitigations configured in flowwler will not be applied by a MikroTik peer - use blackhole or subnet-blackhole mitigation types for groups served by MikroTik routers.

To install blackhole routes, add a routing filter that matches the blackhole community and sets the next-hop to a discard interface (e.g. a Blackhole route or a dummy interface):

/routing filter add chain=flowwler-in action=accept bgp-communities=65535:666 \ set-bgp-nexthop=192.0.2.254 /* set to your discard next-hop */ add chain=flowwler-in action=discard