Software Version: 1.3.11+
Routing Engine: BIRD 2 (v2.17+)
Syntax Layer: MikroTik RouterOS v7 Scripting Layer
Corresponding PDF Document: docs/RoutingFilters.pdf
Routing Filters in DebTik serve as the central policy enforcement mechanism for dynamic routing protocols (principally BGP and OSPF). The underlying implementation is powered by the industry-standard, high-performance BIRD 2 routing daemon, coupled with an intuitive graphical interface and a syntax compatibility layer inspired by MikroTik RouterOS v7.
Internal, bgp-in, bgp-out). Each chain compiles in BIRD 2 into a procedural function function fn_filter_<Chain>() and a standalone filter filter filter_<Chain>.#, e.g., 10, 20, 30). Lower numbers execute first.accept; or reject; action terminates filter evaluation immediately for that candidate route. The decision is final.reject;).OutputNetworks / Static Blackhole prefixes) and redistribution sources (Connected / Static) are safely preserved and never dropped by the terminal default reject, unless a user rule explicitly discards them.| Feature / Capability | Description & Implementation Details |
|---|---|
| v7 Procedural Scripting | Native if (condition) { actions; } syntax supporting composite logical operators (&&, \|\|, !). |
| CIDR & Subnet Ranges | Prefix matching with variable length bounds (e.g., dst in 10.0.0.0/8{24,28}) and exact mask checks (net.len = 24). |
| BGP Traffic Engineering | Full control over BGP Local Preference, MED Metric, AS-Path Prepending, and BGP Community tagging. |
| Named Lists | Reusable named BGP Community Lists and AS-Path Lists to simplify complex filtering rules into concise definitions. |
| Visual Rule Wizard | Built-in modal form assistant with one-click Quick Templates for instant, error-free rule generation. |
Routing Filters are managed via the DebTik Web Dashboard under Routing → Policy Filters.
| Tab Name | RouterOS Path | Description & BIRD 2 Backend Role |
|---|---|---|
| Rules | /routing filter rule |
Executable policy rules. Defines match criteria and actions (Accept/Reject/Set). Compiles directly into BIRD 2 filter blocks. |
| Community Lists | /routing filter community-list |
Named sets of BGP Communities (e.g., 65000:100). Compiles into define comm_<Name> = [...]. |
| AS Lists | /routing filter num-list |
Named lists of Autonomous System Numbers (ASNs / Ranges). Compiles into define aslist_<Name> = [...]. |
Internal).Rule Order) up or down to adjust evaluation priority.bgp-in, bgp-out, Internal, isp-primary).10, 20, 30...) is recommended for future insertions.For ease of use, each rule editor features a collapsible Visual Rule Wizard that builds valid script code automatically:
192.168.0.0/16 or 0.0.0.0/0).24-32 or ge 24).any, bgp, ospf, connected, static.accept (permit), reject (deny), passthrough (modify & fall through).Available Quick Templates:
0.0.0.0/0: Matches default route.Drop RFC1918: Drops 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16.Len <= /24: Enforces standard ≤ /24 global prefix limit.Loc-Pref 150: Sets local preference 150.AS-Prepend 2x: Prepends local AS twice.Reject: Unconditional drop.DebTik dynamically compiles MikroTik RouterOS v7 procedural rule expressions into native BIRD 2 filter syntax.
| RouterOS v7 Syntax | BIRD 2 Compiled Output | Description & Usage Example |
|---|---|---|
dst in A.B.C.D/M |
net ~ [ A.B.C.D/M+ ] |
Tests if prefix belongs to subnet. E.g., dst in 10.0.0.0/8 (matches /8 through /32). |
dst in A.B.C.D/M{L,H} |
net ~ [ A.B.C.D/M{L,H} ] |
Subnet match bounded by prefix lengths. E.g., dst in 192.168.0.0/16{24,28} (/24 to /28 only). |
dst == A.B.C.D/Mor dst = A.B.C.D/M |
net = A.B.C.D/M |
Exact prefix and netmask match. E.g., dst == 0.0.0.0/0 (default route only). |
dst != A.B.C.D/M |
net != A.B.C.D/M |
Negative match; excludes a specific prefix. |
dst-len == Ndst-len <= N, >= N |
net.len = Nnet.len <= N, >= N |
Prefix length evaluation. E.g., net.len <= 24 prevents routes more specific than /24. |
protocol <name> |
source = RTS_<NAME> |
Route origin check: bgp (RTS_BGP), ospf (RTS_OSPF), connected (RTS_DEVICE), static (RTS_STATIC). |
bgp-communities includes A:B |
(A, B) ~ bgp_community |
Evaluates if a route contains a specific community. E.g., bgp-communities includes 65000:100. |
bgp-communities in ListName |
bgp_community ~ comm_ListName |
Evaluates if any route community matches an entry in a defined Community List. |
bgp-as-path in ListName |
bgp_path.last ~ aslist_ListName |
Evaluates if neighbor AS belongs to a defined AS List. |
bgp-as-path "pattern" |
bgp_path ~ [= * pattern * =] |
Regular expression matching across the AS-Path. E.g., bgp-as-path "^65000_". |
&&, \|\|, ! |
&&, \|\|, ! |
Logical conjunctions: AND (&&), OR (\|\|), NOT (!). |
| Action / Set Syntax | BIRD 2 Output | Routing Effect & Description |
|---|---|---|
accept; |
accept; |
Terminal permit. Route is accepted and filter evaluation terminates immediately. |
reject; / discard; |
reject; |
Terminal deny. Route is dropped and filter evaluation terminates immediately. |
passthrough; |
(non-terminal) | Non-terminal. Executes modification statements and falls through to next rule. |
set bgp-local-pref <N>; |
bgp_local_pref = <N>; |
BGP Local Preference (default 100). Higher value = preferred outbound exit path. |
set bgp-med <N>; |
bgp_med = <N>; |
BGP Multi-Exit Discriminator (MED). Lower value = suggested inbound path for neighbor AS. |
set bgp-path-prepend <N>; |
bgp_path.prepend(...); |
Prepends local AS 1 to 10 times to discourage traffic over backup transit links. |
set bgp-communities.add <A:B>; |
bgp_community.add((A,B)); |
Appends a BGP Community to the route without overwriting existing tags. |
set bgp-communities.delete <A:B>; |
bgp_community.delete((A,B)); |
Removes a specific BGP Community from the route attribute set. |
set distance <N>; |
preference = <N>; |
Administrative Distance / Preference for local routing table selection. |
set gw <IP>; |
gw = <IP>; |
Forcibly overrides the Next-Hop IP gateway for the route. |
Named lists allow defining reusable sets of BGP Communities and Autonomous System numbers. Using named lists ensures policy rules remain compact, maintainable, and readable across multiple peers.
/routing filter community-list)BGP Communities are 32-bit values attached to routes to convey policy intents such as peer classification, traffic engineering, blackholing, or geographic scope.
AWMN_COMM, UPSTREAM_BLACKHOLE).AS:Value format or well-known keywords (no-export, blackhole). E.g., 65000:100, 6610:200, no-export.# 1. Configured in DebTik Web UI (Community List: AWMN_COMM):
# Name: AWMN_COMM | Communities: 65000:100, 6610:200
#
# 2. Generated BIRD 2 global definition in /etc/bird/bird.conf:
define comm_AWMN_COMM = [ (65000, 100), (6610, 200) ];
# 3. Usage inside filter rules (RouterOS v7 syntax):
if (bgp-communities in AWMN_COMM) {
set bgp-local-pref 150;
accept;
}
/routing filter num-list)AS Lists define sets of Autonomous System Numbers (ASNs). They are commonly used to verify the origin AS or detect specific upstream transit carriers in an AS-Path:
TIER1_ISPS, GRNET_PEERS).65000-65010) and discrete ASNs separated by commas (e.g., 6610, 17244, 3356).# 1. Configured in DebTik Web UI (AS List: TIER1_ISPS):
# Name: TIER1_ISPS | Range: 65000-65010, 6610, 17244, 3356
#
# 2. Generated BIRD 2 global definition in /etc/bird/bird.conf:
define aslist_TIER1_ISPS = [ 65000..65010, 6610, 17244, 3356 ];
# 3. Usage inside filter rules (checks neighbor/last AS in path):
if (bgp-as-path in TIER1_ISPS) {
set bgp-local-pref 200;
accept;
}
[!NOTE] In BIRD 2, list constants (
comm_...andaslist_...) are emitted at the top of/etc/bird/bird.confbefore any filter functions or protocol definitions. This ensures they are universally accessible to all filter chains.
Policy chains are associated with BGP sessions via the peer configuration form (Routing → BGP Routing → Peers), using the In-Filter and Out-Filter fields.
master4.accept; are installed in the routing table. Routes hitting reject; or unmatched routes are discarded (Default Deny).In BIRD 2, an Out-Filter processes all candidate routes in the routing table. To prevent unintentional route leaks while protecting locally originated networks, DebTik (v1.3.11+) employs a 3-tier evaluation hierarchy:
| Priority Level | BIRD 2 Mechanism | Description & Behavioral Guarantee |
|---|---|---|
| Tier 1: User Policy | fn_filter_<Chain>(); |
Highest priority. User-defined chain rules execute first. An explicit reject; drops the route immediately. An explicit accept; exports the route immediately with all modifications applied. |
| Tier 2: Advertised Nets | if proto = "bgp_nets_..." then accept; |
Automated protection. If a route was not explicitly matched by user rules, but was declared in the peer's Output Networks or global BGP Networks (Static blackhole), it is automatically accepted for advertisement. |
| Tier 3: Redistribution | if source = RTS_DEVICE then accept;if source ~ [ RTS_STATIC ]... |
Redistribution. If the peer has Redistribute Connected or Redistribute Static checked, those routes are automatically accepted unless rejected in Tier 1. |
| Default Deny | reject; |
Any remaining unmatched route is safely discarded, preventing unintended transit leaks. |
# Generated BIRD 2 block for peer with OutFilter: "Internal"
protocol bgp bgp_bgp_peer_1 {
description "ebgp-internal-Primcast";
local 192.168.129.226 as 65001;
neighbor 192.168.129.225 as 65555;
ipv4 {
import filter filter_Internal;
export filter {
# Tier 1: User policy rules evaluation
fn_filter_Internal();
# Tier 2: Automated protection for declared peer & static networks
if proto = "bgp_nets_bgp_bgp_peer_1" then accept;
if proto = "bgp_static_nets" then accept;
# Tier 3: Connected & Static route redistribution (if enabled)
if source = RTS_DEVICE then accept;
if source ~ [ RTS_STATIC, RTS_INHERIT ] then accept;
# Default Deny
reject;
};
};
}
The following battle-tested configuration patterns illustrate common real-world routing scenarios.
Goal: Accept internet routes, discard RFC1918/bogon subnets, drop over-specifics (> /24), and accept default route:
# Chain: isp-in | Rule 10: Accept Default Route (0.0.0.0/0)
if (dst == 0.0.0.0/0) { accept; }
# Chain: isp-in | Rule 20: Drop private RFC1918 & martian IP ranges
if (dst in 10.0.0.0/8 || dst in 172.16.0.0/12 || dst in 192.168.0.0/16 || dst in 127.0.0.0/8) { reject; }
# Chain: isp-in | Rule 30: Reject prefixes more specific than /24
if (net.len > 24) { reject; }
# Chain: isp-in | Rule 40: Accept all other legitimate public routes with standard Local-Pref
if (true) { set bgp-local-pref 100; accept; }
Goal: Prefer ISP-A for all traffic. Use ISP-B as backup by boosting ISP-A Local-Pref and prepending on ISP-B:
# ISP-A Inbound (Chain: isp-a-in): High Local-Pref 200 (Preferred Exit)
if (true) { set bgp-local-pref 200; accept; }
# ISP-B Inbound (Chain: isp-b-in): Standard Local-Pref 100 (Backup Exit)
if (true) { set bgp-local-pref 100; accept; }
# ISP-B Outbound (Chain: isp-b-out): AS-Prepend 2x (Discourages Inbound Traffic on ISP-B)
if (dst in 192.168.130.0/24 || dst in 192.168.131.0/24) {
set bgp-path-prepend 2;
accept;
}
Goal: Tag customer routes with a BGP Community without interrupting sequential rule processing:
# Chain: customer-out | Rule 10: Non-terminal community tag
if (dst in 100.64.0.0/16) {
set bgp-communities.add 65000:500;
passthrough;
}
# Chain: customer-out | Rule 20: Terminal permit for specific block
if (dst in 100.64.64.0/24) { accept; }
Goal: Drop traffic to an internal IP under attack by signaling upstream provider blackholing:
# Chain: isp-out | Rule 5: Signal RTBH /32 to upstream carrier
if (dst == 192.168.131.100/32) {
set bgp-communities.add 65535:666; # Well-known Blackhole Community
set gw 192.0.2.1; # Discard Next-Hop
accept;
}
DebTik provides complete operational visibility into active route policies via both the Web Dashboard and the BIRD 2 command-line interface (birdc).
birdc) Command Reference| CLI Command | Diagnostic Purpose & Usage |
|---|---|
birdc show protocols |
Summarizes status of all dynamic routing protocols (BGP, OSPF, Static), session uptime, and state (Established/Active/Idle). |
birdc show protocols all <peer> |
Primary diagnostic command. Displays detailed filter counters: Import updates, rejected, filtered, accepted and Export updates, rejected, accepted. |
birdc show route export <peer> |
Displays exactly which routes are currently being advertised to the peer after Out-Filter policy evaluation. |
birdc show route import <peer> |
Displays all candidate routes imported from the neighbor after In-Filter processing. |
birdc show route filtered <peer> |
Lists routes that were rejected or filtered out by policy rules. |
birdc show route for <prefix> all |
Inspects detailed route attributes for a specific prefix (AS-Path, Communities, Local Preference, Next-Hop). |
birdc restart <peer> |
Instantly resets the BGP session with the peer for immediate policy re-evaluation and route refresh. |
[!IMPORTANT] Q1: The peer is Established but my static/blackhole networks are not being advertised. Why?
Answer: Verify whether an Out-Filter is attached to the peer. In release 1.3.11+, declared Advertised Networks (Output Networks / Static Blackhole) are exported automatically. Confirm by runningbirdc show route export <peer>to inspect the active outbound route list.[!TIP] Q2: I wrote a rule using '==' and BIRD 2 rejected it with a syntax error.
Answer: BIRD 2 strictly requires single=for equality tests. In release 1.3.11+, DebTik automatically sanitizes double equals (==) to single equals (=) upon save, preventing syntax failures regardless of script style.[!NOTE] Q3: How do I know if my In-Filter is dropping routes I need?
Answer: Runbirdc show protocols all <peer>and check the Route change stats → filtered counter. If this counter is incrementing, executebirdc show route filtered <peer>to identify the specific dropped prefixes and adjust your filter rules.[!NOTE] Q4: What happened to the 'Select Rules' tab?
Answer: Select Rules was a RouterOS v7 legacy concept with no equivalent in BIRD 2. In release 1.3.11, it was completely removed to ensure platform reliability and eliminate confusion, as all routing policies are cleanly achieved using standard Filter Rules.