nftables: paket siaran duplikat antar segmen

Aug 18 2020

Kami memiliki kotak Debian Buster (nftables 0.9.0, kernel 4.19) yang terpasang pada empat segmen jaringan yang berbeda. Tiga dari segmen ini adalah rumah bagi perangkat yang menjalankan Syncthing, yang menjalankan penemuan lokalnya sendiri melalui siaran ke port UDP 21027. Dengan demikian, perangkat tidak dapat "melihat" satu sama lain karena siaran tidak melintasi segmen; kotak Buster itu sendiri tidak berpartisipasi dalam cluster sinkronisasi.

Meskipun kami dapat menyelesaikan ini dengan menjalankan penemuan Syncthing atau server relai di kotak Buster, kami diminta untuk tidak menggunakannya (alasan seputar konfigurasi dan perangkat yang menjelajah ke situs lain). Oleh karena itu, kami sedang mencari solusi berbasis nftables; pemahaman saya adalah bahwa ini biasanya tidak dilakukan, tetapi untuk membuat ini berfungsi, kita harus:

  • Cocokkan paket masuk pada UDP 21027
  • Salin paket-paket itu ke antarmuka segmen lain yang perlu mereka lihat
  • Ubah IP tujuan dari paket baru agar sesuai dengan alamat siaran segmen baru (sambil mempertahankan IP sumber karena protokol penemuan dapat mengandalkannya)
  • Keluarkan siaran baru tanpa diduplikasi lagi

Hanya tiga dari segmen terlampir yang berpartisipasi dengan perangkat; semua menggunakan subnet mask sebagai / 24.

  • Segmen A (eth0, 192.168.0.1) tidak boleh diteruskan
  • Segmen B (eth1, 192.168.1.1) harus diteruskan ke segmen A.
  • Segmen C (eth2, 192.168.2.1) harus diteruskan ke A dan B

Yang paling dekat yang kita miliki dengan aturan yang berfungsi sejauh ini adalah (aturan DNAT / MASQ lain dan penyaringan lokal dihilangkan agar singkatnya):

table ip mangle {
    chain repeater {
        type filter hook prerouting priority -152; policy accept;
        ip protocol tcp return
        udp dport != 21027 return
        iifname "eth1" ip saddr 192.168.2.0/24 counter ip daddr set 192.168.1.255 return
        iifname "eth0" ip saddr 192.168.2.0/24 counter ip daddr set 192.168.0.255 return
        iifname "eth0" ip saddr 192.168.1.0/24 counter ip daddr set 192.168.0.255 return
        iifname "eth2" ip saddr 192.168.2.0/24 counter dup to 192.168.0.255 device "eth0" nftrace set 1
        iifname "eth2" ip saddr 192.168.2.0/24 counter dup to 192.168.1.255 device "eth1" nftrace set 1
        iifname "eth1" ip saddr 192.168.1.0/24 counter dup to 192.168.0.255 device "eth0" nftrace set 1
    }
}

Penghitung menunjukkan bahwa aturan dipatuhi, meskipun tanpa daddr setaturan, alamat siaran tetap sama seperti pada segmen asal. nft monitor tracemenunjukkan setidaknya beberapa paket mencapai antarmuka yang dimaksudkan dengan IP tujuan yang benar, tetapi kemudian mendarat di kait masukan untuk kotak itu sendiri dan tidak terlihat oleh perangkat lain pada segmen tersebut.

Apakah hasil yang kita cari di sini dapat dicapai dalam praktiknya, dan jika demikian, dengan aturan yang mana?

Jawaban

1 A.B Aug 21 2020 at 03:53

Masih mungkin untuk menggunakan nftables dalam keluarga netdev (bukan keluarga ip ) untuk kasus ini, karena hanya ingress yang diperlukan (nftables masih belum menyediakan jalan keluar ). Perilaku dari dupdan fwddi hook masuk sama persis dengan tc-mirred 's mirrordan redirect.

Saya juga membahas detail kecil: menulis ulang alamat sumber Ethernet ke alamat MAC antarmuka keluar Ethernet baru, seperti yang akan dilakukan untuk paket yang benar-benar dirutekan, bahkan jika itu berfungsi untuk Anda tanpa ini. Jadi alamat MAC antarmuka harus diketahui sebelumnya. Saya meletakkan dua yang diperlukan ( eth0 dan eth1 ) dalam variabel / definisi makro, yang harus diedit dengan nilai yang benar.

define eth0mac = 02:0a:00:00:00:01
define eth1mac = 02:0b:00:00:00:01

table netdev statelessnat
delete table netdev statelessnat

table netdev statelessnat {
    chain b { type filter hook ingress device eth1 priority 0;
        pkttype broadcast ether type ip ip daddr 192.168.1.255 udp dport 21027 jump b-to-a
        
    }

    chain c { type filter hook ingress device eth2 priority 0;
        pkttype broadcast ether type ip ip daddr 192.168.2.255 udp dport 21027 counter jump c-to-b-a
    }

    chain b-to-a {
        ether saddr set $eth0mac ip daddr set 192.168.0.255 fwd to eth0 } chain c-to-b-a { ether saddr set $eth1mac ip daddr set 192.168.1.255 dup to eth1 goto b-to-a
    }
}
1 T2PS Aug 19 2020 at 21:44

Sunting: bagi siapa pun yang menemukan ini nanti, jawaban yang diterima dari AB memberikan solusi murni-nft.

Terima kasih atas saran AB, ini sekarang berfungsi menggunakan tc daripada aturan nftables murni:

tc qdisc add dev eth2 ingress
tc filter add dev eth2 ingress \
    protocol ip u32 \
    match ip dst 192.168.2.255 \
    match ip protocol 17 0xff \
    match ip dport 21027 0xffff \
    action nat ingress 192.168.2.255/32 192.168.0.255 \
    pipe action mirred egress mirror dev eth0 \
    pipe action nat ingress 192.168.0.255/32 192.168.1.255 \
    pipe action mirred egress redirect dev eth1

tc qdisc add dev eth1 ingress
tc filter add dev eth1 ingress \
    protocol ip u32 \
    match ip dst 192.168.1.255 \
    match ip protocol 17 0xff \
    match ip dport 21027 0xffff \
    action nat ingress 192.168.1.255/32 192.168.0.255 \
    pipe action mirred egress redirect dev eth0

Pemahaman saya tentang filter ini adalah mereka cocok dengan paket siaran masuk untuk port UDP 21027, NAT mereka ke alamat siaran untuk masing-masing subnet yang dimaksudkan lainnya ( ingress, untuk mengubah IP tujuan daripada IP sumber yang nat egressakan berubah), lalu duplikat / redirect paket NAT ke antrian output antarmuka lain.

Menjadi pemula dengan tc, ini mungkin bukan cara terbaik untuk menyelesaikan masalah, tetapi ini bekerja dalam hal membuat siaran pengumuman berjalan lintas segmen (dan Syncthing dengan senang hati menemukan node baru).