3

アップデート

  • 01-27ter: rp_filter情報追加
  • 01-27bis: 9.04 ボックスは別のインターフェイスで動作することに注意してください。
  • 01-27: インターフェイス構成情報とパケットの解析を追加。

元の投稿

私は 2 つの非常によく似たハードウェア構成 (デュアル Xeon CPU と 2 つのイーサネット ポートを搭載した SuperMicro 1U システム) を持っています。 17 サーバー)。これらは両方とも、さまざまな他のサーバーがブロードキャストUDPパケットをさまざまなポートに送信している同じネットワークに接続されたeth1を持っています。両方のホストで、eth1 で tcpdump を使用すると、これらのブロードキャスト UDP パケットが到着することがわかります。

ただし、8.04 のボックスでは、簡単なプログラムで問題なくリッスンできますが、9.04 のボックスでは、同じプログラムがそれらを受信することはありません。高レベルの概要として、一方では動作するが他方では動作しないサンプルHaskellプログラムを次に示します(両方で同じバージョンのGHCを使用):

import Network.Socket

port = 5515

main :: IO ()
main = do
     do sock <- socket AF_INET Datagram defaultProtocol
        bindSocket sock $ SockAddrInet (fromIntegral port) iNADDR_ANY
        loop sock
    where
        loop sock =
             do msg <- recv sock 2048
                print msg
                loop sock

問題がGHCで非常に奇妙なものであった場合(両方で同じビルドですが)、同じことを行うCプログラムを書きました:

#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>

#define BUFLEN 512
#define NPACK 10
#define PORT 5515

void diep(char *s)
{
    perror(s);
    exit(1);
}

void showb(int s) {
    int val, len, retval;
    len = sizeof(val);
    retval = getsockopt(s, SOL_SOCKET, SO_BROADCAST, &val, &len);
    printf("showb retval=%d val=%d\n", retval, val);
}

int main(int argc, char **argv)
{
    struct sockaddr_in si_me, si_other;
    int s, i, slen=sizeof(si_other);
    char buf[BUFLEN];

    if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
        diep("socket");

    showb(s);
    i = 1;
    if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &i, sizeof(i))==-1)
        diep("setsockopt");
    showb(s);

    memset((char *) &si_me, 0, sizeof(si_me));
    si_me.sin_family = AF_INET;
    si_me.sin_port = htons(PORT);
    si_me.sin_addr.s_addr = htonl(INADDR_ANY);
    if (bind(s, &si_me, sizeof(si_me))==-1)
        diep("bind");

    puts("Listening.");

    for (i=0; i<NPACK; i++) {
        if (recvfrom(s, buf, BUFLEN, 0, &si_other, &slen)==-1)
            diep("recvfrom()");
        printf("Received packet from %s:%d\nData: %s\n\n",
               inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port), buf);
    }

    close(s);
    return 0;
}

この場合の楽しみのために、ソケットの SO_BROADCAST フラグもオンにして、それがオンになることを確認していますが、プログラムの動作には違いはなく、同じです。 . 8.04 でビルドされたバイナリを 9.04 ボックスにコピーした場合、またはその逆の場合でも、8.04 ボックスで実行されているプログラムは UDP ブロードキャスト パケットを認識し、9.04 ボックスは認識しません。

私は何を間違っていますか?

アップデート 01-27:

動作中の (8.04) ホストの ip link および ip ether の出力は次のとおりです。

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1362 qdisc pfifo_fast qlen 1000
    link/ether 00:30:48:d3:4b:06 brd ff:ff:ff:ff:ff:ff
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 100
    link/ether 00:30:48:d3:4b:07 brd ff:ff:ff:ff:ff:ff
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1362 qdisc pfifo_fast qlen 1000
    link/ether 00:30:48:d3:4b:06 brd ff:ff:ff:ff:ff:ff
    inet 192.168.228.130/28 brd 192.168.228.143 scope global eth0
    inet6 fe80::230:48ff:fed3:4b06/64 scope link 
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 100
    link/ether 00:30:48:d3:4b:07 brd ff:ff:ff:ff:ff:ff
    inet 172.40.4.130/24 brd 172.40.4.255 scope global eth1
    inet6 fe80::230:48ff:fed3:4b07/64 scope link 
       valid_lft forever preferred_lft forever

稼働していない (9.04) サーバーの場合:

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1362 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:30:48:d9:38:da brd ff:ff:ff:ff:ff:ff
3: eth2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
    link/ether 00:1b:21:36:19:fd brd ff:ff:ff:ff:ff:ff
4: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 100
    link/ether 00:30:48:d9:38:db brd ff:ff:ff:ff:ff:ff
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1362 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:30:48:d9:38:da brd ff:ff:ff:ff:ff:ff
    inet 192.168.228.132/28 brd 192.168.228.143 scope global eth0
    inet6 fe80::230:48ff:fed9:38da/64 scope link 
       valid_lft forever preferred_lft forever
3: eth2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
    link/ether 00:1b:21:36:19:fd brd ff:ff:ff:ff:ff:ff
4: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 100
    link/ether 00:30:48:d9:38:db brd ff:ff:ff:ff:ff:ff
    inet 172.40.4.132/24 brd 172.40.4.255 scope global eth1
    inet6 fe80::230:48ff:fed9:38db/64 scope link 
       valid_lft forever preferred_lft forever

どちらの場合も、eth1 はブロードキャストが到着するポートであることに注意してください。

プログラムが受信していないサンプル ブロードキャスト パケットの完全なデコード (動作していない 9.04 サーバー上の tshark から) を次に示します。

Frame 193555 (271 bytes on wire, 271 bytes captured)
    Arrival Time: Jan 25, 2010 08:00:00.535345000
    [Time delta from previous captured frame: 0.001508000 seconds]
    [Time delta from previous displayed frame: 0.000000000 seconds]
    [Time since reference or first frame: 6590.956186000 seconds]
    Frame Number: 193555
    Frame Length: 271 bytes
    Capture Length: 271 bytes
    [Frame is marked: False]
    [Protocols in frame: eth:ip:udp:data]
Ethernet II, Src: Cisco_aa:c0:28 (00:d0:bb:aa:c0:28), Dst: Broadcast (ff:ff:ff:ff:ff:ff)
    Destination: Broadcast (ff:ff:ff:ff:ff:ff)
        Address: Broadcast (ff:ff:ff:ff:ff:ff)
        .... ...1 .... .... .... .... = IG bit: Group address (multicast/broadcast)
        .... ..1. .... .... .... .... = LG bit: Locally administered address (this is NOT the factory default)
    Source: Cisco_aa:c0:28 (00:d0:bb:aa:c0:28)
        Address: Cisco_aa:c0:28 (00:d0:bb:aa:c0:28)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
    Type: IP (0x0800)
Internet Protocol, Src: 192.166.1.120 (192.166.1.120), Dst: 255.255.255.255 (255.255.255.255)
    Version: 4
    Header length: 20 bytes
    Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00)
        0000 00.. = Differentiated Services Codepoint: Default (0x00)
        .... ..0. = ECN-Capable Transport (ECT): 0
        .... ...0 = ECN-CE: 0
    Total Length: 257
    Identification: 0xfad3 (64211)
    Flags: 0x04 (Don't Fragment)
        0... = Reserved bit: Not set
        .1.. = Don't fragment: Set
        ..0. = More fragments: Not set
    Fragment offset: 0
    Time to live: 252
    Protocol: UDP (0x11)
    Header checksum: 0xc0f9 [correct]
        [Good: True]
        [Bad : False]
    Source: 192.166.1.120 (192.166.1.120)
    Destination: 255.255.255.255 (255.255.255.255)
User Datagram Protocol, Src Port: 56172 (56172), Dst Port: 5515 (5515)
    Source port: 56172 (56172)
    Destination port: 5515 (5515)
    Length: 237
    Checksum: 0x01ba [correct]
        [Good Checksum: True]
        [Bad Checksum: False]
Data (229 bytes)

0000  41 37 30 33 34 30 38 30 30 30 30 30 30 31 31 30   A703408000000110
0010  4b 52 53 50 49 4f 50 4b 32 49 4b 52 34 32 30 31   KRSPIOPK2IKR4201
0020  45 32 32 32 35 33 30 30 32 31 30 30 30 30 30 30   E222530021000000
0030  30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
0040  30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
0050  30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
0060  30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
0070  30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
0080  30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
0090  30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
00a0  30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
00b0  30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
00c0  30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
00d0  30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
00e0  30 30 30 30 ff                                    0000.
    Data: 413730333430383030303030303131304B525350494F504B...

動作中の 8.04 サーバーで取得したダンプからの同じパケットに対してこれを比較しましたが、パケット自体は同一です。唯一の違いは、フレーム番号 (pcap ファイル内) と、パケットが受信された時間 (1.224 ミリ秒の差です。2 つのホストが同じ NTP サーバーを使用していることを考えると、この差は大きいように見えますが、まったく不合理ではありません)。

更新 01-27bis

さらに実験して、8.04 ホストで独自のブロードキャスト パケットを生成し、9.04 ホストに送信しました。9.04 ホストは、8.04 ホストがパケットを送信して eth0 または eth1 に到着すると、パケットを問題なく受信します。

更新 01-27ter

sp 3; sysctl -a 2>/dev/null | grep '\.rp_filter' | sort8.04 ホストでの出力は次のとおりです。

net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.eth0.rp_filter = 0
net.ipv4.conf.eth1.rp_filter = 0
net.ipv4.conf.lo.rp_filter = 1

9.04 ホストでは次のようになります。

net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.eth0.rp_filter = 1
net.ipv4.conf.eth1.rp_filter = 1
net.ipv4.conf.eth2.rp_filter = 1
net.ipv4.conf.lo.rp_filter = 0
4

1 に答える 1

1

したがって、問題は net.ipv4.conf.eth1.rp_filter sysctl 設定です。8.04 ボックスで 0 に設定して、緩いリバース パス チェックを行っています。これは、任意のインターフェイスでルーティングできる任意の宛先からパケットが着信する可能性があることを意味します。9.04 ボックスでは、厳密なチェックを行っていました。つまり、パケットへの応答が別のインターフェイスに送信される場合、インターフェイスに到着したパケットを拒否するということです。

eth1 から 255.255.255.255 に到着するパケットは、255.255.255.255 がローカルネットワークのブロードキャスト アドレスであるにもかかわらず、これらのパケットの送信元がローカル ネットワーク上にないため、すべてが正常に機能していた場合に受信すべきではないパケットです。基本的に、フィードを受信するネットワークで何かが正しく設定されておらず、この設定ミスに対処する必要があります。

于 2010-01-27T05:40:14.680 に答える