为什么 conntrackd 没有复制状态?

为什么 conntrackd 没有复制状态?

我遇到了主动/主动防火墙群集的问题,其中防火墙中的连接跟踪状态似乎未被复制。

它是主动/主动的,因为我有两个通过不同 ISP 连接的路由器和一个通过 BGP 提供的网络范围。数据如何路由回来由 BGP 决定。因此路由是不对称的。这两个防火墙在内部网络上联网,我有一个虚拟 IP 作为 Windows 服务器的默认路由。

当两个防火墙都在运行,并且内部服务器尝试连接时,回复将通过辅助防火墙(没有连接状态记录的防火墙)返回。因此回复将被丢弃,而不会路由到发起请求的服务器。

我以为 conntrackd 可以解决这个问题,但我似乎无法让它工作。也许我误解了它的工作原理。我可以让 conntrackd 复制 iptables 状态吗?它真的可以在主动/主动模式下工作吗?状态是实时复制的吗?

以下是我的 conntrackd.conf 文件包含的内容。

Sync {
  Mode ALARM {
    RefreshTime 15
    CacheTimeout 180
  }

  Multicast {
    IPv4_Address 225.0.0.50
    Group 3780
    IPv4_Interface 10.0.0.100
    Interface eth2
    SndSocketBuffer 1249280
    RcvSocketBuffer 1249280
    Checksum on
  }
}

General {
  Nice -20
  HashSize 32768
  HashLimit 131072
  LogFile on
  Syslog on
  LockFile /var/lock/conntrack.lock
  UNIX {
    Path /var/run/conntrackd.ctl
    Backlog 20
  }
  NetlinkBufferSize 2097152
  NetlinkBufferSizeMaxGrowth 8388608
  Filter From Userspace {
    Protocol Accept {
      TCP
    }

    Address Ignore {
      IPv4_address 127.0.0.1 # loopback
      IPv4_address 10.0.0.100 # dedicated link0
      IPv4_address 10.0.0.101 # dedicated link1
      IPv4_address x.x.x.130 # Internal ip
    }
  }
}

其余 conntrackd 相同,除了多播部分中的 IPv4_interface 为 10.0.0.101。过滤器部分中的内部 IP 以 131 结尾

我已经设置防火墙规则以接受输入到 225.0.0.50/32 并输出到 225.0.0.50/32。

我已将模式设置为 ALARM,但首先尝试了 FTFW。似乎都不起作用。

我的内核版本是:3.11.0。

抱歉,我的剪切和粘贴功能在 Virtual Box 窗口中不起作用。不过,我只想说,当我运行:sudo conntrackd -i 时,它会将 ESTABLISHED tcp 连接列为输出,这是我使用 ssh 创建的。

然而,在另一台路由器上,同样的命令没有产生任何输出。我认为这应该意味着状态没有传输到另一台路由器上。

有任何想法吗?


更新:我在每台机器上运行了 tcpdump -i eth2,我可以看到从另一台路由器本地到达的 UDP 数据包,其目的地是多播地址 225.0.0.50 端口 3780,长度为 68 字节。

如果我发起 ssh 连接,我会立即在 tcpdump 上看到活动,断开连接也会发生同样的情况。否则,该消息的常规心跳会通过。因此很明显,路由器正在发送数据包,但 conntrackd 会忽略它们吗?我可以打开一些隐藏的调试吗?


更新 2:好的,经过几天的谷歌搜索和查看源代码,我发现 conntrackd 正在复制状态,但最终会进入外部缓存。要提交规则,您需要运行 conntrackd -c。显然,conntrackd 旨在用于主动/备份模式。

似乎在某个时候引入了一个名为 CacheWriteThrough 的新选项。但后来被删除了。conntrack 可以做主动/主动吗?我似乎找不到答案。

答案1

好吧,经过几天的挫折、查阅少量文档甚至阅读源代码后,我终于搞清楚了。

Mode FTFW {
     [...]
     DisableExternalCache On
}

对于非对称路由场景,您需要禁用外部缓存。否则,对于主动/备份,您需要使用默认关闭,并在 keepalived 中设置 notify_master、notify_backup、notify_fault 设置。

设置 CacheWriteThrough 已被删除并替换为 DisableExternalCache。

这些脚本用于将外部连接状态缓存提交给持有 IP 的路由器。启用 DisableExternalCache 后,这些脚本不再需要,因为状态已提交。

答案2

我发现,如果活动服务器重新启动,防火墙/路由器对上的活动/备份配置(没有 nopreempt)会失败。当主服务器关闭时,备份服务器接管,并且 primary-backup.sh 脚本将外部缓存提交给内核表,正如预期的那样。所有连接都保持活动状态。但是,当(原始)主服务器重新启动并再次接管时,由于其外部缓存为空,primary-backup.sh 脚本将空的外部缓存提交给内核表,并且所有连接都被 iptables 丢弃。我通过在脚本开头附近添加几行来解决这个问题:

case "$1" in
  primary)
    #
    # request resynchronization with master firewall replica
    #
    # Note: this is an attempt to fix problem after reboot of original master,
    # which had no entries in external cache and so resulted in empty
    # conntrack table
    #
    $CONNTRACKD_BIN -C $CONNTRACKD_CONFIG -n
    if [[ $? -eq 1 ]]
    then
        logger "ERROR: failed to invoke conntrackd -n"
    fi

    #
    # commit the external cache into the kernel table
    #
    # etc

相关内容