- Creates address list entries from manual entries on a per interface basis
- Creates address list entries for multiple interfaces when routes match a certain BGP community (ours in this case are 37314:500)
- Creates address list entries for multiple interfaces when routes match a certain BGP community (customers in this case are 37314:3000)
- Creates address list entries for certain interfaces when routes match an array of custom per interface BGP communities
- Removes stale entries which are older than 3.5 days, all entries have their comment updated with the Unix Epoch time stamp each time the script is run.
Code: Select all
/system scheduler
add interval=1d name="Update Interface filter address lists" on-event=\
"/system script run \"update_interface_address_lists\"" policy=read,write start-date=\
jan/01/1970 start-time=01:30:00
/system script
add name=update_interface_address_lists owner=admin policy=read,write source="# {\"<address list>\";\
\_<1 = prefixes matching 37314:500>; <1 = prefixes matching 37314:3000>; {<manual prefixes>};\
\_{<custom bgp communities>}};\r\
\n# Examples:\r\
\n# {\"filter-ether1\"; 1; 1; {10.1.0.0/16; 10.2.0.0/16}; {}};\r\
\n# {\"filter-ether2\"; 0; 0; {}; {\"37314:2000\"}};\r\
\n:local ifs { \r\
\n {\"filter-external\"; 1; 1; {}; {}};\r\
\n {\"filter-external-src\"; 1; 0; {}; {}};\r\
\n {\"filter-ixp\"; 1; 1; {10.20.200.0/22}; {}};\r\
\n {\"filter-upstream1-vlan43\"; 1; 1; {}; {}};\r\
\n {\"filter-upstream2-vlan418\"; 1; 1; {}; {}};\r\
\n};\r\
\n\r\
\n:global fncJD do={\r\
\n :local months [:toarray \"jan,feb,mar,apr,may,jun,jul,aug,sep,oct,nov,dec\"];\r\
\n :local jd;\r\
\n :local M [:pick \$1 0 3];\r\
\n :local D [:pick \$1 4 6];\r\
\n :local Y [:pick \$1 7 11];\r\
\n :for x from=0 to=([:len \$months] - 1) do={\r\
\n :if ([:tostr [:pick \$months \$x]] = \$M) do={ :set M (\$x + 1) };\r\
\n }\r\
\n :if (\$M = 1 || \$M = 2) do={\r\
\n :set Y (\$Y-1);\r\
\n :set M (\$M+12);\r\
\n }\r\
\n :local A (\$Y/100);\r\
\n :local B (\$A/4);\r\
\n :local C (2-\$A+\$B);\r\
\n :local E (((\$Y+4716) * 36525)/100);\r\
\n :local F ((306001*(\$M+1))/10000);\r\
\n :local jd (\$C+\$D+\$E+\$F-1525);\r\
\n :return \$jd;\r\
\n};\r\
\n\r\
\n:global timestamp do={\r\
\n :global fncJD \$fncJD;\r\
\n :local currtime [/system clock get time];\r\
\n :local jdnow [\$fncJD [/system clock get date]];\r\
\n :local days (\$jdnow - 2440587);\r\
\n :local ore [:pick \$currtime 0 2];\r\
\n :local minute [:pick \$currtime 3 5];\r\
\n :local secunde [:pick \$currtime 6 8];\r\
\n :return ((\$days * 86400) + (\$ore * 3600) + (\$minute * 60) + \$secunde - [/system clock get gmt-offset]);\r\
\n}\r\
\n:local timenow [\$timestamp];\r\
\n\r\
\n:local arrayXpush do={\r\
\n :local arrX value=[:toarray \$1];\r\
\n :if ([:len \$arrX] = 0) do={ :set \$arrX value=[:toarray \"\"]; };\r\
\n :local arrXlen value=[:len \$arrX];\r\
\n :local valX value=[:tostr \$2];\r\
\n :if (\$valX = \"\") do={ :return value=\$arrX; };\r\
\n :local posX value=([:tostr \$3]);\r\
\n :if (\$posX = \"\") do={ :set \$posX value=(\$arrXlen + 1); };\r\
\n :set \$posX value=([:tonum \$posX] + 0);\r\
\n :if (\$posX < 0) do={:set \$posX value=0};\r\
\n :if (\$posX > \$arrXlen) do={:set \$posX value=\$arrXlen};\r\
\n :if (\$posX = 0) do={:return value=(\$valX,\$arrX)};\r\
\n :if (\$posX = \$arrXlen) do={:return value=(\$arrX,\$valX)};\r\
\n :return value=([:pick \$arrX 0 (\$posX - 1)],\$valX,[:pick \$arrX (\$posX - 1) \$arrXlen]);\r\
\n};\r\
\n\r\
\n:local addresslist do={\r\
\n :local name (\$1);\r\
\n :local destination (\$2);\r\
\n :local timenow (\$3);\r\
\n :if ([:typeof [:find \$destination \"/32\"]] = \"num\") do={:set destination [:pick \$destination 0 [:find \$destination \"/\"]]};\r\
\n /ip firewall address-list set [ find list=\"\$name\" and address=\"\$destination\" ] comment=\$timenow;\r\
\n :do {/ip firewall address-list add list=\$name address=\$destination comment=\$timenow} on-error={};\r\
\n}\r\
\n\r\
\n:foreach if in=\$ifs do={\r\
\n :local name (\$if->0);\r\
\n :local prefixes (\$if->3);\t# load manual prefixes\r\
\n :local destination;\r\
\n :foreach community in=(\$if->4) do={\r\
\n :foreach i in=[ /ip route find where active and bgp-communities ~ \$community ] do={\r\
\n :set destination [ /ip route get \$i dst-address ];\r\
\n :set prefixes [\$arrayXpush \$prefixes \$destination];\r\
\n }\r\
\n }\r\
\n :foreach destination in=\$prefixes do={\$addresslist \$name \$destination \$timenow};\r\
\n}\r\
\n\r\
\n:foreach k,community in={1=\"37314:500\"; 2=\"37314:3000\"} do={\r\
\n :set k [:tonum \$k];\r\
\n :local prefixes ({});\r\
\n :local destination;\r\
\n :foreach i in=[ /ip route find where active and bgp-communities ~ \$community ] do={\r\
\n :set destination [ /ip route get \$i dst-address ];\r\
\n :set prefixes [\$arrayXpush \$prefixes \$destination];\r\
\n }\r\
\n :foreach if in=\$ifs do={\r\
\n :local name (\$if->0);\r\
\n if (\$if->\$k = 1) do={\r\
\n :foreach destination in=\$prefixes do={\$addresslist \$name \$destination \$timenow};\r\
\n }\r\
\n }\r\
\n}\r\
\n\r\
\n:local expired ([\$timenow] - 302400);\t# expire after 3.5 days\r\
\n:foreach if in=\$ifs do={\r\
\n :local name (\$if->0);\r\
\n :local i;\r\
\n :foreach i in=[ /ip firewall address-list find where list=\$name ] do={\r\
\n :local comment [ /ip firewall address-list get \$i comment ];\r\
\n :local added [:tonum \$comment];\r\
\n :if (\$added = \$comment) do={\r\
\n :if (\$added < \$expired) do={\r\
\n /ip firewall address-list remove \$i;\r\
\n }\r\
\n }\r\
\n }\r\
\n}\r\
\n"
Sample firewall rules to:
- Drop traffic entering interfaces that are members of the 'external' interface list, when not to our or downstream customer prefixes (filter-external)
- Drop traffic entering interfaces that are members of the 'external' interface list, where from our prefixes. (filter-external-src)
- Drop traffic leaving external interfaces where the source IPs are not part of those interface lists. (eg filter-upstream1-vlan43)
Code: Select all
/interface list
add name=external
/interface list member
add interface=ixp list=external
add interface=upstream1-vlan43 list=external
add interface=upstream2-vlan418 list=external
/ip firewall raw
add action=accept chain=prerouting comment="Track - packets destined for this router:" dst-address-type=local
add action=drop chain=prerouting comment="Drop - In 'external' interface list - not to \"filter-external' address list:" dst-address-list=!filter-external in-interface-list=external
add action=drop chain=prerouting comment="Drop - In 'external' interface list - from \"filter-external-src' address list:" in-interface-list=external src-address-list=filter-external-src
/ip firewall filter
add action=drop chain=forward out-interface=ixp src-address-list=!filter-ixp
add action=drop chain=forward out-interface=upstream1-vlan43 src-address-list=!filter-upstream1-vlan43
add action=drop chain=forward out-interface=upstream2-vlan418 src-address-list=!filter-upstream2-vlan418