当前位置: 首页 > 工具软件 > ebtables > 使用案例 >

ebtables规则arpreply

笪昌翰
2023-12-01

创建网桥br0,将物理接口ens35加入到br0。动态获得地址192.168.1.130,注意br0的MAC地址为00:0c:29:e6:3f:76。

# ip link add br0 type bridge
# ip link set ens35 master br0
# 
# dhclient br0
# 
# ip addr
5: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 00:0c:29:e6:3f:76 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.130/24 brd 192.168.1.255 scope global dynamic br0
       valid_lft 604798sec preferred_lft 604798sec
    inet6 fe80::20c:29ff:fee6:3f76/64 scope link 
       valid_lft forever preferred_lft forever

增加ebtables规则arpreply,当网桥接收到arp请求时,回复MAC地址10:11:12:13:14:15。

# ebtables -t nat -A PREROUTING -p arp --arp-opcode Request -j arpreply --arpreply-mac 10:11:12:13:14:15
# 
# 
# ebtables -t nat -L
Bridge table: nat

Bridge chain: PREROUTING, entries: 1, policy: ACCEPT
-p ARP --arp-op Request -j arpreply --arpreply-mac 10:11:12:13:14:15

登录另外一台主机(192.168.1.201),使用arping测试,如下显示得到的MAC地址为arpreply规则中配置的值。

# arping 192.168.1.130
ARPING 192.168.1.130 from 192.168.1.201 eth0
Unicast reply from 192.168.1.130 [10:11:12:13:14:15]  1.342ms
Unicast reply from 192.168.1.130 [10:11:12:13:14:15]  2.104ms
Unicast reply from 192.168.1.130 [10:11:12:13:14:15]  1.965ms
^CSent 3 probes (1 broadcast(s))
Received 3 response(s)

查看本机的邻居表,并没有缓存主机192.168.1.201的硬件地址。原因是arpreply默认的动作是DROP,报文没有进入ARP子系统进行处理。

# ip neigh
192.168.1.1 dev br0 lladdr 40:62:31:08:e1:fa STALE

以下,将arpreply的动作设置为ACCEPT。

# ebtables -t nat -D PREROUTING 1 
# ebtables -t nat -A PREROUTING -p arp --arp-opcode Request -j arpreply --arpreply-mac 10:11:12:13:14:15 --arpreply-target ACCEPT 
# 
# ebtables -t nat -L 
Bridge table: nat

Bridge chain: PREROUTING, entries: 1, policy: ACCEPT
-p ARP --arp-op Request -j arpreply --arpreply-mac 10:11:12:13:14:15 --arpreply-target ACCEPT

再次登录测试主机(192.168.1.201),arping结果如下,每个ARP请求,回到了两个回复报文,一个为arpreply规则中配置的MAC地址,另外一个为ARP子系统回复的br0真实MAC地址。

# arping 192.168.1.130
ARPING 192.168.1.130 from 192.168.1.201 eth0
Unicast reply from 192.168.1.130 [10:11:12:13:14:15]  1.391ms
Unicast reply from 192.168.1.130 [00:0C:29:E6:3F:76]  1.419ms
Unicast reply from 192.168.1.130 [10:11:12:13:14:15]  2.160ms
Unicast reply from 192.168.1.130 [00:0C:29:E6:3F:76]  2.231ms
Unicast reply from 192.168.1.130 [10:11:12:13:14:15]  1.755ms
Unicast reply from 192.168.1.130 [00:0C:29:E6:3F:76]  2.064ms
^CSent 3 probes (1 broadcast(s))
Received 6 response(s)

本机中缓存了测试主机(192.168.1.201)的硬件地址。

# ip neigh
192.168.1.1 dev br0 lladdr 40:62:31:08:e1:fa STALE
192.168.1.201 dev br0 lladdr 00:0c:29:38:40:6b STALE

以上arpreply规则配置,会影响局域网中的所有ARP请求,导致ARP地址欺骗。安全起见限定源MAC地址00:0c:29:38:40:6b(测试主机192.168.1.130的MAC),这样只有测试主机的ARP请求,才回复arpreply规则指定的MAC地址。

# ebtables -t nat -A PREROUTING -p arp --arp-opcode Request --src 00:0c:29:38:40:6b -j arpreply --arpreply-mac 10:11:12:13:14:15
# 
# ebtables -t nat -L --Lc --Ln   
Bridge table: nat

Bridge chain: PREROUTING, entries: 1, policy: ACCEPT
1 -p ARP -s 00:0c:29:38:40:6b --arp-op Request -j arpreply --arpreply-mac 10:11:12:13:14:15 , pcnt = 4 -- bcnt = 184

或者,限定ARP报文的源地址。

# ebtables -t nat -A PREROUTING -p arp --arp-opcode Request --arp-ip-src 192.168.1.201 -j arpreply --arpreply-mac 10:11:12:13:14:15
# 
# ebtables -L -t nat
Bridge table: nat

Bridge chain: PREROUTING, entries: 1, policy: ACCEPT
-p ARP --arp-op Request --arp-ip-src 192.168.1.201 -j arpreply --arpreply-mac 10:11:12:13:14:15

arpreply注册

注册ebt_arpreply_tg_reg目标target,hook点仅支持NAT表的NF_BR_PRE_ROUTING。

static struct xt_target ebt_arpreply_tg_reg __read_mostly = {
    .name       = "arpreply",
    .revision   = 0,
    .family     = NFPROTO_BRIDGE,
    .table      = "nat",
    .hooks      = (1 << NF_BR_NUMHOOKS) | (1 << NF_BR_PRE_ROUTING),
    .target     = ebt_arpreply_tg,
    .checkentry = ebt_arpreply_tg_check,
    .targetsize = sizeof(struct ebt_arpreply_info),
    .me     = THIS_MODULE,
};
static int __init ebt_arpreply_init(void)
{
    return xt_register_target(&ebt_arpreply_tg_reg);
}

配置合法性检查函数ebt_arpreply_tg_check,如果使用的为基础chain链,target不能为EBT_RETURN,可以使用EBT_ACCEPT、EBT_DROP和EBT_CONTINUE。但是,对于用户自创建的chain,不受此限制。另外,协议必须指定为ARP,并且不能进行取反操作。

static int ebt_arpreply_tg_check(const struct xt_tgchk_param *par)
{
    const struct ebt_arpreply_info *info = par->targinfo;
    const struct ebt_entry *e = par->entryinfo;
    
    if (BASE_CHAIN && info->target == EBT_RETURN)
        return -EINVAL;
    if (e->ethproto != htons(ETH_P_ARP) ||
        e->invflags & EBT_IPROTO)
        return -EINVAL;
    if (ebt_invalid_target(info->target))
        return -EINVAL;

arpreply规则的报文处理函数如下。首先确保报文为ARP请求,并且,硬件地址长度为以太网的地址长度,协议为IPv4协议,协议地址长度为4。

static unsigned int
ebt_arpreply_tg(struct sk_buff *skb, const struct xt_action_param *par)
{
    const struct ebt_arpreply_info *info = par->targinfo;
    const __be32 *siptr, *diptr;
    __be32 _sip, _dip;
    const struct arphdr *ap;
    struct arphdr _ah;
    const unsigned char *shp;
    unsigned char _sha[ETH_ALEN];

    ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah);
    if (ap == NULL)
        return EBT_DROP;

    if (ap->ar_op != htons(ARPOP_REQUEST) ||
        ap->ar_hln != ETH_ALEN ||
        ap->ar_pro != htons(ETH_P_IP) ||
        ap->ar_pln != 4)
        return EBT_CONTINUE;

以下,由ARP请求报文中取得发送者硬件地址shp,发送者IP地址,以及目标的IP地址。

    shp = skb_header_pointer(skb, sizeof(_ah), ETH_ALEN, &_sha);
    if (shp == NULL)
        return EBT_DROP;

    siptr = skb_header_pointer(skb, sizeof(_ah) + ETH_ALEN,
                   sizeof(_sip), &_sip);
    if (siptr == NULL)
        return EBT_DROP;

    diptr = skb_header_pointer(skb,
                   sizeof(_ah) + 2 * ETH_ALEN + sizeof(_sip),
                   sizeof(_dip), &_dip);
    if (diptr == NULL)
        return EBT_DROP;

对应于ARP报文中的ar_sha、ar_sip和ar_tip。

     /*
      *  Ethernet looks like this : This bit is variable sized however...
      */
    unsigned char       ar_sha[ETH_ALEN];   /* sender hardware address  */
    unsigned char       ar_sip[4];      /* sender IP address        */
    unsigned char       ar_tha[ETH_ALEN];   /* target hardware address  */
    unsigned char       ar_tip[4];      /* target IP address        */

发送ARP响应报文,其中目标硬件地址使用arpreply规则中配置的MAC地址,对应于以上的报文字段ar_tha。返回值为规则中指定值。

    arp_send(ARPOP_REPLY, ETH_P_ARP, *siptr,
         (struct net_device *)xt_in(par),
         *diptr, shp, info->mac, shp);

    return info->target;

内核版本 5.10

 类似资料: