Send an /32 IP to Blackhole Community ISP with BGP

Hello all,

We would like to send a /32 to blackhole communities using BGP¨to our ISP.

The BGP status is (ISP and IP update for security) :

/routing bgp peer print status
Flags: X - disabled, E - established
 0 E name="HE" instance=default remote-address=X.X.X.X remote-as=XXXX
     tcp-md5-key="" nexthop-choice=default multihop=no route-reflect=no
     hold-time=3m ttl=255 in-filter=connected-in out-filter=connected-in
     address-families=ip default-originate=never remove-private-as=no
     as-override=no passive=no use-bfd=no remote-id=X.X.X.X
     local-address=X.X.X.X uptime=19h23m11s prefix-count=533710
     updates-sent=5 updates-received=990899 withdrawn-sent=1
     withdrawn-received=95011 remote-hold-time=3m used-hold-time=3m
     used-keepalive-time=1m refresh-capability=yes as4-capability=yes
     state=established

We have try a routing test with this example “http://wiki.mikrotik.com/wiki/Routing_Questions” but do not work.

Can you help me with the exactly process ?


Many thanks for your reply,

Sincerely

I see you have the same filter for inbound and outbound advertisement filters.
I’m not sure how that filter is built, but chances are, you should use different filters - even if they have the same rules, you may in the future need to change one filter but not the other.

Basically, good practice would be to make your outbound filter to HE work like this:
Allow your prefix(es) with prefix-length x-24 where X is the actual size of your CIDR block.
So if you have two prefixes- x.x.x.0/22 and y.y.y.0/23 - your basic output filter should allow x.x.x.0/22 prefix-length=22-24 and y.y.y.0/23 prefix-length=23-24.

If you know that you will never want to advertise sub-sets of your CIDR blocks, then just allow the exact prefix without specifying the range of prefix-lengths. With public EBGP, stricter is better. You NEVER want to accidentally leak something out to the world unintentionally, even if your provider’s filters will protect you.

Usually the provider gives you a specific community string to use for blackhole advertisements. e.g. 65400:911 (check your documentation from Hurricane Electric for further details).
Make the next rule in your filter allow 0.0.0.0/0 prefix-length=32 and only those with the community 65400:911
Last rule of the filter = block all

Now, whenever you want to blackhole something, create a /32 static blackhole route in your router, and on the configuration of this route, go into the attributes tab and add the 65400:911 community.
Finally, you need to get this /32 route into BGP - do so by either adding a network origination statement to BGP (I would prefer this method) or else enabling “redistribute from static” on the BGP instance.

Hello ZeroByte,

Follow your instruction, i have create 2 filters :

/routing filter print
Flags: X - disabled
 0   chain=FILTER-IN invert-match=no action=passthrough set-bgp-prepend-path=""
 1   chain=FILTER-OUT prefix=x.x.x.x/23 prefix-length=23-24 invert-match=no action=passthrough set-bgp-prepend-path=""

Update the BGP :

/routing bgp peer print status
Flags: X - disabled, E - established
 0 E name="HE" instance=default remote-address=x.x.x.x remote-as=6939 tcp-md5-key="" nexthop-choice=default multihop=no
     route-reflect=no hold-time=3m ttl=255 in-filter=FILTER-IN out-filter=FILTER-OUT address-families=ip default-originate=never
     remove-private-as=no as-override=no passive=no use-bfd=no remote-id=x.x.x.x local-address=x.x.x.x uptime=7m9s
     prefix-count=532742 updates-sent=3 updates-received=534784 withdrawn-sent=0 withdrawn-received=197 remote-hold-time=3m
     used-hold-time=3m used-keepalive-time=1m refresh-capability=yes as4-capability=yes state=established

For the next step, you say

Make the next rule in your filter allow 0.0.0.0/0 prefix-length=32 and only those with the community 65400:911
Last rule of the filter = block all

Im realy not sure, when i put this rule, i lost connectivity of the router of not ? (block all) > Im at 1 hours in car of the router…

Thanks for your reply :slight_smile:


Sincerely
NL

Dear,

I have try this command :

/ip route add dst-address=X.X.X.X/32 type blackhole comment=blackhole bgp-communities=0000:666

Where X.X.X.X/32 is IP attacked.

Ping down :slight_smile:
I stay the information from HE if BGP communities have replicated correctly. Its correct for you ?


In second, i would like to launch this script with Wanguard, script is :

# Script add to Blackhole
#
:local ip "IPFROMWANGUARD";
#
/ip route add dst-address="$ip"/32 type blackhole comment="$ip"/32 bgp-communities=0000:666



# Script remove to Blackhole
#
:local ip "IPFROMWANGUARD";
#
/ip route remove [find comment=""$ip"/32""];

it seems you correct ?

Thanks for all your reply,

Sincerely
NL

Dear,

I have check with my ISP, do not work for the latest reply…

So i have put a new filter :

/routing filter add chain=FILTER-IN prefix=X.X.X.X/32 invert-match=no action=accept set-bgp-communities=6939:666

I can see the advertisement :

/routing bgp advertisements print
                                                                       PEER     PREFIX               NEXTHOP          AS-PATH                                                             ORIGIN     LOCAL-PREF
HE       X.X.X.X/32      X.X.X.X                                                                        igp

But can ping…

Thanks for your reply

action should be ‘accept’ on these rules
Rule 0 is the same as having no filter at all, but that’s okay - it’s actually good to make an explicit “allow all” chain because it makes it obvious later when viewing your configuration that you INTEND to allow everything.

Rule 1 should be ‘accept’ as the action also - because you will add an explicit ‘discard’ at the end of the chain (see below). If you simply pass-through, then you’re basically not doing anything based on the match - the chain will continue. Pass-through is good for actions like “prepend AS” - because you want to do this and continue with other actions like set / remove communities / etc… If you just want to allow something, then make that the action.

In any case, it is good practice to be very explicit in BGP filter rules. Even if the default behavior is “accept” - make that the last rule so that it’s obvious that this is exactly what you mean. In BGP, you NEVER want something to happen which you didn’t intend. (you can get banned from exchanges if you are known to make mistakes in bgp)

Putting drop / discard / accept / etc - as actions in filter chains will not kick you out of a router or block access in any way. Although they behave like a firewall rule chain, they’re not packet filters. They’re prefix filters - which means they allow / block / mangle the various routing advertisements that a routing protocol is allowed to learn or advertise.

So a block rule won’t block transport to an IP address (well, if it causes your router to have no route to reach the IP, then that would break things, of course, but it won’t make the router FILTER anything) - it only means “if someone says ‘I have a route to reach such-and-such a destination’ then ignore it” - or maybe the action is “accept it, but mark it as a very bad route.”

If you’re worried, make a static route /32 to the IP address you’re coming from, and you won’t be able to kick yourself out by making a bad routing filter.

The problem is your prefix X.X.X.X/32 - it should be X.X.X.X/23 prefix-length=32 . . . .

prefix=1.2.3.0/32 means exactly the address 1.2.3.0
prefix=1.2.2.0/23 means anything in the range 1.2.2.0 - 1.2.3.255

I’m going to try to explain this concept here for you, but if it still doesn’t make sense, then I suggest that you do some reading, watch some instructors on youtube, and make some experiments in the lab until you understand.

Here we go - here is a basic explanation of how prefix list filters match:

prefix x.x.x.x/m defines an IP and range - a matching prefix will be exactly this prefix, or a “subnet” of it.
Prefix-length means what size netmask is allowed to be used in an advertisement… it limits the size of the subnets which will match.

So if you have a rule—> prefix=1.2.2.0/23 prefix-length=24-26 action=accept
This will permit: 1.2.2.128/25, 1.2.2.64/26, and 1.2.3.0/24
It will not match:
1.2.2.0/23 (prefix is too short)
1.2.5.0/24 (prefix is not inside the allowable range)
1.2.3.0/29 (prefix is too long)
These would be compared against any remaining rules in the filter.
If there are no more rules, then the filter (apparently) accepts by default.
Prefix list matching is confusing for a while, but once the light clicks in your mind, it will make perfect sense.
Basically the x.x.x.x/23 means allow any prefix that is from x.x.x.0 through x.x.x+1.255 - prefix length means that whatever nemask is on the prefix advertisement, it must be in the range you specified, or else it will be dropped.
Of course, invalid prefix definitions are dropped anyway, so you can’t say 1.2.2.64/25 - that’s not valid so it doesn’t matter that the address and mask are “in range”
Finally, a prefix cannot be shorter than a rule:
prefix=1.0.0.0/16 prefix-length=1-32 … even if you say this, a prefix 1.0.0.0/8 will be blocked because it contains IP addresses that are not inside the range you listed, even though the prefix is valid and the netmask is between 1 and 32.

Hello ZeroByte,

Finaly its work :slight_smile:

Add to blackhole :

/routing filter add chain=FILTER-OUT prefix=$1/32 invert-match=no action=accept set-bgp-communities=xxxx:xxx comment=$1/32
/routing bgp network add network=$1/32 synchronize=no
/routing bgp peer resend-all

Del of blackhole :

/routing filter remove [find comment=$1/32];
/routing bgp network remove [find network=$1/32]"
/routing bgp peer resend-all

Where $1 is the IP attacked :slight_smile:

Many thanks :slight_smile:

Nico

Hi Nico,
why you use /routing bgp peer resend-all ?

I don’t think it should be necessary, since the network statement is being added after the filter is in place.
A slightly easier way to do this would be to selectively redistribute static routes into BGP so that adding the network and updating the filter chains aren’t necessary:

/routing filter
add chain=BGP-out-global protocol=static bgp-communities=200:666 action=accept
add chain=BGP-out-global protocol=static action=discard 
/routing bgp instance
set default out-filter=BGP-out-global redistribute-static=yes

With this in place, you only need to create/remove static routes and they’ll automatically be sent to the peers whose out-filters permit it.
/ip route add type=blackhole dst=192.0.2.42/32 bgp-communities=200:666
/ip route add type=blackhole dst=192.0.2.64/29 bgp-communities=200:666
Both of these would cause the local router to blackhole these destinations, and the inclusion of the community 200:666 will allow them to be redistributed into BGP via the first rule of the BGP-out-global chain. Note that this example filter doesn’t restrict the prefix-length - basically you’re trusting yourself to only put sensible things into the blackhole routing community - but if you want a safety net, also put a prefix-length=29-32 clause on the blackhole community rule in the chain.

I would not recommend to redistribute any routes. Create static blackholes with bgp-communities, and add each network to the /routing bgp network section using synchronize=yes.

While I agree with you that one should always originate routes properly, in my observation, a black hole route fits neatly into the category of “things that make sense to redistribute.” I’ve made many, many posts all over the Mikrotik forum telling people that they should properly originate all routes - that redistributed routes have subtle differences about them that can come back to haunt you later when you’ve learned more about routing. However, being that a black hole route for DDoS mitigation is:
a) temporary
b) a long prefix (which wins out regardless of other metrics / traffic engineering tactics / etc)
c) issued in an emergency situation - thus you want it to be as fast and as easy as possible to execute
d) not propagated to the entire global BGP table
.. I feel that having an incomplete origin really doesn’t matter much since each provider receiving the prefix is just going to black hole the destination without repeating the advertisement to their other peers. Also, this emergency tactic should only be left operational for the absolute minimum duration possible, so it’s not like you’re spewing garbage into the global routing table.
Of course, if someone DOES wish to use redistribute-static=yes, then they need to be careful and make sure that their global filter only allows specific information into the BGP table. If it allows all routes to get dumped willy-nilly into BGP, then that is definitely a bad thing.

Hi ZeroByte,

I use this for filter;
chain=to_MYISP prefix=xxx.xx.xx.0/22 prefix-length=32 invert-match=no
action=accept set-bgp-prepend-path="" set-bgp-communities=1111:111

and also found this script from internet and tring to modify it for me to send ddosed ips to blackhole

:log info "BGP Blackhole updater starting";

:local refresh;
:set refresh false;

Add addresses to BGP networks

:foreach address in=[/ip firewall address-list find list=ddosed disabled=no] do={
:local id;
:set id [/ip firewall address-list get $address address]

:local rtExists;
:set rtExists false;

:foreach nets in=[/routing bgp network find network="$id/32"] do={
:set rtExists true;
:put "$id already in BGP networks";
}
:if ($rtExists = false) do={
/routing bgp network add network="$id/32" synchronize=no;
:set refresh true;
:put "$id added to BGP networks";
}
}

Remove addresses from BGP networks that are not in ACL

:foreach route in=[/routing bgp network find synchronize=no] do={
:local addr;
:set addr [/routing bgp network get $route network]

:local addrsize;
:set addrsize [:len $addr]
:set addr [ :pick $addr 0 ($addrsize-3) ];

:local aclExists;
:set aclExists false;

:foreach addrs in=[/ip firewall address-list find list=ddosed address=$addr disabled=no] do={
:set aclExists true;
:put "$addr still listed in ACL";
}
:if ($aclExists = false) do={
:local netid;
:set netid [/routing bgp network find network="$addr/32"]

/routing bgp network remove $netid;
:set refresh true;

:put "$addr removed from BGP networks";
}
}
:if ($refresh = true) do={
:log info "BGP Blackhole updater triggered BGP peer resend-all"
:put "Doing BGP peer resend-all"
/routing bgp peer resend-all
}
:log info "BGP Blackhole updater finished";

This rule means that any /32 prefix inside of your IP block is going to get community 9121:666 set to it (clearing any preexisting communities) as it is sent to MYISP. I assume from the chain’s name that it is applied to the peer configuration, not the BGP instance itself, and I also assume there are other rules in this chain which you didn’t show… because if this is the only rule, then your router will actually send the entire BGP table to MYISP and you’re depending on the ISP’s in-filter to stop you from advertising something wrong.

As for the script, at a glance, this seems like it should work. The key is that it uses synchronize=no on the BGP network definitions so that you don’t need to also add static blackhole routes for the /32.

The script you’re using may have been written before a scripting feature I like was created:
on-error={ }

For adding black hole prefixes, instead of having to do all of the checking logic in-script, you could have a single command:

:foreach A in=[/ip firewall address-list find list=Blackholes] do={ :do { /routing bgp network add network=[/ip firewall address-list get $A address] synchronize=no } on-error={} }

This syntax will add everything from the Blackholes list and simply do nothing for error condition (i.e. the item is already in the list)
Note that there is a nested :do command inside of the do={} block of the :foreach command. :do allows for the on-error{} condition so that the script will not halt if the :do command fails.

The removal code still needs to compare everything.

ZeroByte,
thanks for your quick answer and help.
here is my routing filter
/routing filter
add action=discard chain=ospf-out prefix=xxx.xxx.xx.x/30(wan interface ip) prefix-length=30-32 ( I use this for ospf)
add action=accept chain=to_MYISP prefix=xxx.xxx.xx.x/22 prefix-length=32 set-bgp-communities=1111:111 ( and use this to sent attacked ip adreses to my upstream provider)

and here my bgp instance and bgp peer;
/routing bgp instance
set default as=xxxx client-to-client-reflection=no out-filter=default redistribute-connected=yes

/routing bgp peer
add default-originate=if-installed hold-time=1m30s keepalive-time=10s name=wan out-filter=to_MYISP remote-address=xxx.xxx.xx.xx remote-as=xxx tcp-md5-key=xxxxxxxxx
ttl=default update-source=wan

thesee are my settings and i use Chupaka’ rules at firewall filter;

/ip firewall filter
add action=jump chain=forward comment=Detect-Ddos connection-state=new in-interface=wan jump-target=detect-ddos
add action=return chain=detect-ddos comment=DOS-Exceptions src-address-list=DOS-Exceptions
add action=return chain=detect-ddos comment=Detect-Ddos dst-limit=50,256,src-and-dst-addresses/10s
add action=add-dst-to-address-list address-list=ddosed address-list-timeout=1m chain=detect-ddos comment=Detect-Ddos
add action=add-src-to-address-list address-list=ddoser address-list-timeout=1d chain=detect-ddos comment=Detect-Ddos
add action=drop chain=forward comment=Detect-Ddos connection-state=new dst-address-list=ddosed src-address-list=ddoser

and with the other script that i sent you before, im trying to do something like or i will try to change it for me. and add the ddosed ip’s to bgp network as /32 automatically. so i think i may get out of some ddos attack.

also can you check bgp settings for me may be something wrong there.

Thank you verymuch.

This means that you’re sending a default GW announcement to your ISP - i.e. you’re telling your ISP that YOU are the way to go to reach the Internet. I guarantee that they’re blocking this, but you should definitely disable that. (do it when you can handle a momentary BGP bounce because changing peer settings causes Mikrotiks to reset the BGP peering session)
Question - is the BGP session ONLY used to announce black hole routes, or are you also intending to originate your own /22 block as well? Your current filter setup doesn’t let you announce your master prefix or any subset of it except for the /32 blackholes.

Hi zerobyte,

Disbable what ? Dont understAnd that :frowning: disable routing filter ? Or disable default-originate=if-installed ?
We use bgp session for internet. Betwen upstreamprovider and oursystem. And isp gave me blackhole communite to sent attacked ip to their blackhole. /22 block taken from ripe and set them to my AS number.
Sory i dont have enough experince and trying to explain you :slight_smile: thanks for help again.

Disable default-originate=if-installed (change this to “never”)
Your filter rule to_MYISP actually allows everything to be sent. You also need to add another two rules to the end of that chain in this order:

chain=to_MYISP prefix=xxx.xx.xx.0/22 prefix-length=22-24 action=accept
chain=to_MYISP action=discard

Repeat the first of these two rules more times if you have more than one public prefix. (this rule allows you to send /24 or /23 sub-blocks of the master /22, but if you have other ranges than just this one /22, you’ll need to add those as well previous to the discard rule.

I set it like this ;

0 chain=ospf-out prefix=xxx.xxx.xx.xx/30 prefix-length=30-32 invert-match=no action=discard set-bgp-prepend-path=""    
1   chain=to_MYISP prefix=xxx.xxx.xx0/22 prefix-length=32 invert-match=no action=accept set-bgp-prepend-path="" set-bgp-communities=1111:111    
2   chain=to_MYISP prefix=xxx.xxx.x0/22 prefix-length=22-24 invert-match=no action=accept set-bgp-prepend-path=""    
3   chain=to_MYISP invert-match=no action=discard set-bgp-prepend-path=""

I just thought of one thing to be careful of with your configuration- your filter rule will allow ANY /32 route you create to get picked up and broadcast as a blackhole route to your ISP.
You may want to also add some other criteria such as scope=90, or bgp-communities=1111:111 so that if you ever do need to create an actual /32 route from your public space that goes somewhere valid, it won’t get mistakenly picked up as a blackhole route.

If you use scope=90, then this means that when you want to blackhole something, create a static route:
/ip route add dst=b.b.b.b/32 scope=90 type=blackhole
or to match communities:
/ip route add dst=b.b.b.b/32 bgp-communities=1111:111 type=blackhole
(in this case, you wouldn’t need the bgp action = set communities on the blackhole filter rule because you’re setting it on the route)

This is because your instance is redistributing static routes, and the filters (as they stand right now) simply look for /32 routes from your public block, and then announce them to the ISP with a blackhole community. You need to make sure the blackhole filter doesn’t just slap the blackhole community on ANY /32 it sees.

Hi Zero Byte,

I understand that you are not support the routing filter. and you prefer to use scope 90 or bgp-communities. so i removed the filters from routing and also from bgp peer. and i will start to use /ip route add dst=b.b.b.b/32 bgp-communities=1111:111 type=blackhole at the next ddos attack. am I on the correct way ?
and i do some test for this when i use filter and trace to xxx.xxx.xxx.x ip its stops before come to my upstreamprovider. and if ı use blackhole its stop after my upstreamprovider.