web-dev-qa-db-ja.com

Conntrackdキャッシュにtcpセッションが表示されない

conntrackdでやや奇妙な問題が発生しています。フェイルオーバー後にセッションがバックアップに複製される、またはその逆のアクティブ/バックアップシナリオの環境を作成しました。私は、ほとんど同じ構成を使用するツールと他のチュートリアルの 公式マニュアル に従いました。

問題

tcpまたはwgetを使用していくつかのsshセッションを作成すると、conntrack -Lおよびconntrack -E -p tcpで作成されているセッションを確認できます。

root@master:/home/master# conntrack -L
udp      17 22 src=x.x.x.190 dst=x.x.x. sport=138 dport=138 [UNREPLIED] src=x.x.x. dst=x.x.x.190 sport=138 dport=138 mark=0 use=1
udp      17 4 src=x.x.x.9 dst=255.255.255.255 sport=11235 dport=11232 [UNREPLIED] src=255.255.255.255 dst=x.x.x.9 sport=11232 dport=11235 mark=0 use=1
udp      17 21 src=x.x.x.26 dst=255.255.255.255 sport=17500 dport=17500 [UNREPLIED] src=255.255.255.255 dst=x.x.x.26 sport=17500 dport=17500 mark=0 use=1
udp      17 14 src=x.x.x.212 dst=x.x.x. sport=137 dport=137 [UNREPLIED] src=x.x.x. dst=x.x.x.212 sport=137 dport=137 mark=0 use=1
udp      17 18 src=x.x.x.50 dst=x.x.x. sport=62401 dport=3052 [UNREPLIED] src=x.x.x. dst=x.x.x.50 sport=3052 dport=62401 mark=0 use=1
tcp      6 299 ESTABLISHED src=192.168.0.7 dst=x.x.x.58 sport=46026 dport=80 src=x.x.x.58 dst=192.168.0.7 sport=80 dport=46026 [ASSURED] mark=0 use=1

root@master:/home/master# conntrack -E -p tcp
    [NEW] tcp      6 120 SYN_SENT src=192.168.0.7 dst=x.x.x.58 sport=46030 dport=80 [UNREPLIED] src=x.x.x.58 dst=192.168.0.7 sport=80 dport=46030
 [UPDATE] tcp      6 60 SYN_RECV src=192.168.0.7 dst=x.x.x.58 sport=46030 dport=80 src=x.x.x.58 dst=192.168.0.7 sport=80 dport=46030
 [UPDATE] tcp      6 432000 ESTABLISHED src=192.168.0.7 dst=x.x.x.58 sport=46030 dport=80 src=x.x.x.58 dst=192.168.0.7 sport=80 dport=46030 [ASSURED]

しかし、マスターの内部キャッシュまたはバックアップの外部キャッシュではそれらを見ることができず、udpセッションしか見ることができません。 (内部キャッシュと外部キャッシュを投稿できません。大きすぎます。コードの最初のブロックと同じように想像してください。ただし、udpセッションのみです)。つまり、tcpセッションはフェイルオーバー時に破棄され、複製されません。 gwetが一時停止し、ssh接続がフリーズします。マスターが再び引き継いだとしても、セッションはすでに失われています。


Conntrackdの構成は次のとおりです。

Sync {
    Mode FTFW {
        DisableExternalCache Off
        CommitTimeout 1800
        PurgeTimeout 5
    }

    UDP{
        IPv4_address 192.168.0.4
        IPv4_Destination_Address 192.168.0.5
        Port 3780
        Interface eth1
        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
            UDP
            ICMP # This requires a Linux kernel >= 2.6.31
        }
        Address Ignore {
            IPv4_address 127.0.0.1 # loopback
            IPv4_address x.x.x.58
            IPv4_address x.x.x.56
            IPv4_address x.x.x.59
            IPv4_address x.x.x.7
            IPv4_address 192.168.0.4
            IPv4_address 192.168.0.5
            IPv4_address 192.168.0.6
            IPv4_address 192.168.0.7
            IPv4_address 192.168.100.100
        }
    }
}

DisableExternalCache Onこの質問 として使用すると、内部キャッシュと外部キャッシュの両方が空になります(udpセッションも失われます)。 Address Acceptの代わりにAddress Ignoreを使用した場合も同じです。 DisableExternalCache Onは、私が探しているアクティブ/バックアップではなく、アクティブ/アクティブシナリオで使用することもお勧めします。

ファイアウォールルールが受け入れるように設定され、これらの追加ルールが追加されます( netfilter testcase から取得)

[1] iptables -P FORWARD DROP
[2] iptables -A FORWARD -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
[3] iptables -A FORWARD -i eth1 -p tcp --syn -m state --state NEW -j ACCEPT
[4] iptables -A FORWARD -i eth1 -p tcp -m state --state ESTABLISHED -j ACCEPT
[5] iptables -A FORWARD -m state --state INVALID -j LOG
[6] iptables -I POSTROUTING -t nat -s 192.168.0.3 -j SNAT --to 192.168.1.100

他の構成、他の同期モード、変更をコミットするスクリプト、および必要に応じてキャッシュをフラッシュするスクリプトを試しました。しかし、tcpセッションがキャッシュに表示されない理由がわからないようです。何かご意見は?私は何かが足りないのですか?

1
Jimmy_A

たくさんの読書、再構成、外部の助けを借りて、問題は解決しました(ついに悪夢は終わりました)。

問題は、最初に考えたルールセットではなく、構成のAddress Ignore部分にありました。

私が従ったチュートリアルでは、彼らはこう言っています:

「AddressIgnore」ブロックには、ファイアウォールが持つすべてのIPが一覧表示されます。

しかし、彼らはAddress Ignoreがファイアウォールが持っているすべてのIPをリストするべきだとは言いませんでしたローカルインターフェース上

たとえば、テストホストなどの追加のアドレスを配置すると、そのホストから生成されたすべてのトラフィックが無視されます。そのため、期待値テーブルではセッションを確認できましたが、キャッシュでは確認できませんでした。つまり、Address Ignoreブロックは、それ自体の(そしておそらくバックアップの)IPアドレス(loopback、ext、int、VIP)のみをリストする必要があります。

PS:もう1つ言及する必要があるのは、ファイアウォールがファイアウォールIPを偽装するように設定する必要があるということです。そうでない場合、フェイルオーバー時にVIPは所有者を変更しますが、セッションは作成されたマシンのIPを探します。

これを克服するには、snatルールを設定する必要があります。

2
Jimmy_A