菜单

[ Juniper ] 使用 BGP Flowspec 控制上游过滤报文

2020年5月26日 - BGP, Juniper

BGP Flowspec 允许你通过 BGP 分发数据流的控制规则,它通过 BGP NLRI 将规则(如源地址,协议号,端口等)分发给激活了 flow address-family 的设备,使网络设备能快速部署针对数据包的防火墙流控规则。正因为 Flowspec 支持该特性,使得调用 BGP Flowspec 来减轻 DDoS 带来的影响成为了可能。

今天我们使用 BGP Flowspec 来实现控制上游的过滤列表来阻止外界访问我们服务器的功能。

拓扑整图:

VFP3 模拟外界访问的用户,VFP4 为我们的上游路由器,VFP9 为我们的边界路由器,Client-B 模拟我们的服务器。

需求:

下面开始对路由器的配置( 基础 IP 配置,OSPF 配置已经配好,生产环境中与eBGP的连接不需要配置 OSPF,实验环境为了之后实验方便预先配置了 OSPF )

由于 BGP Flowspec 是典型的 控制端-被控端 模式,ISP 路由器作为被控端,我方路由器作为控制端,所以 ISP 路由器只需要激活 Flowspec(当然,实际生产环境中要考虑接受路由白名单的问题),剩余的事情如规则下发都需要在我方路由器(CE)上做。

vMX-VFP9(我方CE路由器):

root@CE-B# show

routing-options {
    flow {
        term-order standard; // 激活 BGP Flowspec,模式为 RFC Standard
    }
    router-id 10.0.0.3;
}
protocols {
    bgp {
        group inet-4 {
            type internal;
            local-address 10.0.0.3;
            family inet {
                unicast; // 激活 IPv4-Unicast SAFI,传递 IPv4 路由
                flow; // 激活 IPv4-Flowspec SAFI,传递 Flowspec 路由
            }
            local-as 100;
            neighbor 10.0.0.2 {
                import import;
                export export;
                peer-as 100;
            }
        }
    }
}
policy-options {
    policy-statement export {
        term inet-flow-export {
            from rib inetflow.0; // 允许 Flowspec 路由出网,路由表为 inetflow.0
            then accept;
        }
        term inet-unicast-export {
            from {
                rib inet.0;
                route-filter 100.64.1.0/24 exact; // 宣告 IPv4 路由
            }
            then accept;
        }
        term last {
            then reject;
        }
    }
    policy-statement import {
        then accept;
    }
}

[edit]

vMX-VFP4(ISP PE 上游路由器):

root@R2# show

routing-options {
    flow {
        term-order standard; // 激活 BGP Flowspec,模式为 RFC Standard
    }
    router-id 10.0.0.2;
}
protocols {
    bgp {
        group inet-4 {
            type internal;
            local-address 10.0.0.2;
            cluster 10.0.0.2;
            local-as 100;
            neighbor 10.0.0.1 {
                import all;
                export all;
                peer-as 100;
            }
            neighbor 10.0.0.3 {
                import all;
                family inet {
                    unicast; // 激活 IPv4-Unicast SAFI,传递/接受 IPv4 路由
                    flow; // 激活 IPv4-Flowspec SAFI,接受 Flowspec 路由(也可以传递)
                }
                export all;
                peer-as 100;
            }
        }
    }
policy-options {
    policy-statement all {
        then accept;
    }
}

基本的配置已完成,我们来检查下 BGP 邻居的建立情况:

root@CE-B# run show bgp summary
Groups: 1 Peers: 1 Down peers: 0
Table          Tot Paths  Act Paths Suppressed    History Damp State    Pending
inet.0
                       6          1          0          0          0          0
inetflow.0
                       0          0          0          0          0          0
Peer                     AS      InPkt     OutPkt    OutQ   Flaps Last Up/Dwn State|#Active/Received/Accepted/Damped...
10.0.0.2                100         81         77       0       0       33:09 Establ
  inet.0: 1/6/5/0
  inetflow.0: 0/0/0/0

inet.0 以及 inetflow.0 邻居已经建立起来了,我们首先来模拟从公网服务器访问我们服务器的情况:

root@R1> ping 100.64.1.2 count 3 source 100.64.0.1
PING 100.64.1.2 (100.64.1.2): 56 data bytes
64 bytes from 100.64.1.2: icmp_seq=0 ttl=62 time=563.488 ms
64 bytes from 100.64.1.2: icmp_seq=1 ttl=62 time=173.453 ms
64 bytes from 100.64.1.2: icmp_seq=2 ttl=62 time=370.806 ms

--- 100.64.1.2 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 173.453/369.249/563.488/159.235 ms

root@R1> ssh 100.64.1.2 source 100.64.0.1
The authenticity of host '100.64.1.2 (100.64.1.2)' can't be established.
ECDSA key fingerprint is SHA256:UGgeGwcaz0+JMrvB1Sh/DEtay3sc3mTrjJYztLLTtHs.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '100.64.1.2' (ECDSA) to the list of known hosts.
root@100.64.1.2's password:

看起来没什么问题,IPv4 路由已经连通了,Ping 以及 SSH 均可成功连通。

现在我们来模拟一种情况:当我们的服务器遭受了大量的针对 SSH 端口的攻击,我们需要发 BGP NLRI 给上游服务器,让上游服务器根据 BGP NLRI 生成对应的防火墙规则来丢弃数据包。这样可以维持原来的链路路径,而且我们还能减少 DDoS 对我们带来的影响。

这种情况,我们需要这样配置:

vMX-VFP9(我方CE路由器)

root@CE-B# show routing-options
flow {
    route deny-ssh {  // 聚合一条规则,名字定义为 deny-ssh
        match {  // 匹配协议类型
            protocol tcp; // TCP 协议
            destination-port 22; // 端口 22 ( SSH 标准端口 )
            destination 100.64.1.2/32; // 目标地址 100.64.1.2 (受攻击服务器)
        }
        then discard; // 动作配置为拒绝
    }
    term-order standard;
}

配置完成后,我们查看 ISP 的路由表以及防火墙规则:

root@R2> show route table inetflow.0 extensive

inetflow.0: 1 destinations, 1 routes (1 active, 0 holddown, 0 hidden)
100.64.1.2,*,proto=6,dstport=22/term:1 (1 entry, 1 announced)
TSI:
KRT in dfwd;
Action(s): discard,count
        *BGP    Preference: 170/-101
                Next hop type: Fictitious, Next hop index: 0
                Address: 0xa1d9dbc
                Next-hop reference count: 1
                Next hop:
                State: <Active Int Ext>
                Peer AS:   100
                Age: 2:28
                Validation State: unverified
                Task: BGP_100_100.10.0.0.3+179
                Announcement bits (1): 0-Flow
                AS path: I
                Communities: traffic-rate:0:0
                Accepted
                Localpref: 100
                Router ID: 10.0.0.3

root@R2> show firewall filter __flowspec_default_inet__

Filter: __flowspec_default_inet__
Counters:
Name                                                Bytes              Packets
100.64.1.2,*,proto=6,dstport=22                         0                    0

可见 ISP 的路由表已经收到了 BGP 发过来的 Flowspec 规则,且已经将其安装至防火墙中。我们再来模拟测试一下从公网访问我们服务器的 SSH 端口:

root@R1> ping 100.64.1.2 count 3 source 100.64.0.1
PING 100.64.1.2 (100.64.1.2): 56 data bytes
64 bytes from 100.64.1.2: icmp_seq=0 ttl=62 time=11.102 ms
64 bytes from 100.64.1.2: icmp_seq=1 ttl=62 time=7.364 ms
64 bytes from 100.64.1.2: icmp_seq=2 ttl=62 time=332.472 ms

--- 100.64.1.2 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 7.364/116.979/332.472/152.384 ms

root@R1> ssh 100.64.1.2 source 100.64.0.1
ssh: connect to host 100.64.1.2 port 22: Operation timed out

再来检查 ISP 路由器的防火墙规则:

root@R2> show firewall filter __flowspec_default_inet__

Filter: __flowspec_default_inet__
Counters:
Name                                                Bytes              Packets
100.64.1.2,*,proto=6,dstport=22                       432                    8

我们可以很清楚的看到针对服务器 100.64.1.2 的 TCP 22 端口包被丢弃,且产生了记录,并且 ICMP 报文未受影响。

我们再来测试,模拟受到 ICMP flood 攻击而屏蔽 ICMP 的现象(放行 TCP,阻止 ICMP ):

vMX-VFP9(我方CE路由器)

root@CE-B# show
inactive: route deny-ssh {
    match {
        protocol tcp;
        destination-port 22;
        destination 100.64.1.2/32;
    }
    then discard;
}
route deny-icmp {
    match {
        protocol icmp;
        icmp-type [ 0 8 ];
    }
    then discard;
}
term-order standard;

再模拟从公网服务器进行访问测试:

root@R1> ping 100.64.1.2 count 3 source 100.64.0.1
PING 100.64.1.2 (100.64.1.2): 56 data bytes

--- 100.64.1.2 ping statistics ---
3 packets transmitted, 0 packets received, 100% packet loss

root@R1> ssh 100.64.1.2 source 100.64.0.1
root@100.64.1.2's password:
Permission denied, please try again.
root@100.64.1.2's password:

再来检查 ISP 的防火墙规则:

root@R2> show firewall filter __flowspec_default_inet__

Filter: __flowspec_default_inet__
Counters:
Name                                                Bytes              Packets
*,*,proto=1,icmp-type=0,=8                            252                    3

可以清楚的观察到测试用的3个 ICMP 报文均被丢弃,实验成功。

总结:

如果您对文章有什么建议或者意见,欢迎发邮件到 bGl1Y2hlbjk1ODYoYXQpZ21haWwuY29t

发表评论

电子邮件地址不会被公开。 必填项已用*标注