Mengubah paket unicast UDP menjadi siaran?

8

Kita perlu membangunkan beberapa komputer di LAN internal kita, dari Internet.
Kami memiliki router yang agak tertutup, dengan sangat sedikit cara untuk mengkonfigurasinya.
Saya ingin menggunakan netfilter (iptables) untuk melakukan ini karena tidak melibatkan daemon atau yang serupa, tetapi solusi lain baik-baik saja.

Apa yang ada dalam pikiran saya:

  • komputer eksternal mengeluarkan paket WOL (Wake-On-LAN) ke alamat IP publik (dengan MAC yang benar di dalamnya)
  • port yang benar terbuka pada router (katakanlah 1234), mengarahkan data ke kotak Linux
  • kotak Linux mengubah paket unicast UDP menjadi paket siaran (konten yang sama persis, hanya alamat tujuan yang diubah menjadi 255.255.255.255 atau 192.168.0.255)
  • paket multicast datang ke setiap NIC, dan komputer yang diinginkan sekarang bangun

Untuk itu, aturan netfilter yang sangat sederhana adalah:
iptables --table nat --append PREROUTING --in-interface eth+ --protocol udp --destination-port 1234 --jump DNAT --to-destination 192.168.0.255

Alas netfilter tampaknya mengabaikan transformasi untuk siaran. 192.168.0.255 dan 255.255.255.255 tidak memberikan apa pun. Juga diuji dengan 192.168.0.0 dan 0.0.0.0
Saya menggunakan tcpdump untuk melihat apa yang terjadi:
tcpdump -n dst port 1234
13:54:28.583556 IP www.xxx.yyy.zzz.43852 > 192.168.0.100.1234: UDP, length 102
dan tidak ada yang lain. Saya harus memiliki baris kedua seperti:
13:54:28.xxxxxx IP www.xxx.yyy.zzz.43852 > 192.168.0.255.1234: UDP, length 102

Jika saya mengalihkan ke alamat non-multicast, semuanya baik-baik saja. Saya memiliki 2 garis yang diharapkan. Tapi jelas ini tidak bekerja untuk WOL.

Apakah ada cara untuk memberitahu netfilter untuk mengeluarkan paket siaran?

Metode lain yang saya pikirkan:

  • gunakan iptables untuk mencocokkan paket yang diinginkan, catat, dan gunakan daemon untuk memantau file log dan nyalakan paket siaran
  • gunakan iptables untuk mengarahkan ulang paket yang diinginkan ke daemon lokal, yang meluncurkan paket siaran (lebih sederhana)
  • gunakan socat (bagaimana?)
Gregory MOUSSAT
sumber
Paket siaran bukan hanya paket yang dikirim ke alamat siaran. Ada bendera untuk soket yang disebut SO_BROADCAST. Saya mencoba mencari tahu bagaimana iptables dapat memodifikasinya.
lgeorget
@ lororget: iptables tidak terkait dengan soket.
Bertrand SCHIT
Memang. Saya tidak melihat tempat yang tepat. Pasti ada opsi di suatu tempat bagi iptables untuk memungkinkannya mengirim paket siaran.
lgeorget
1
Sudahkah Anda mencoba iptables --tabel nat --append PREROUTING --in-interface eth + --protocol udp --destination-port 1234 --jump DNAT - to-destination 192.168.0.0?
lgeorget
@ lororget: terima kasih atas idenya. Tapi hasilnya sama. Saya memperbarui pertanyaan
Gregory MOUSSAT

Jawaban:

12

socatadalah utilitas pembunuh. Letakkan suatu tempat di skrip init Anda:

socat -u -T1 UDP-LISTEN:1234,fork UDP-DATAGRAM:255.255.255.255:5678,broadcast

Beberapa pengguna memiliki masalah dengan UDP-LISTEN, jadi menggunakan UDP-RECV tampaknya lebih baik (peringatan: dapat mengirim paket siaran dalam loop tanpa akhir):

socat -u UDP-RECV:1234 UDP-DATAGRAM:255.255.255.255:5678,broadcast

forkmemungkinkan untuk tetap mendengarkan socat untuk paket berikutnya.
T1batasi umur subproses bercabang menjadi 1 detik.
255.255.255.255lebih umum dari 192.168.0.255. Mengizinkan Anda hanya menyalin-menempel tanpa memikirkan struktur jaringan Anda saat ini. Peringatan: ini mungkin mengirim paket yang disiarkan ke setiap antarmuka.

Saat Anda, saya perhatikan WOL bekerja dengan port apa pun. Saya ingin tahu apakah ini dapat diandalkan. Banyak dokumen hanya berbicara tentang port 0, 7 dan 9.
Ini memungkinkan untuk menggunakan port non-pivilegied, sehingga Anda dapat berjalan socatdengan pengguna nobody.

Terima kasih kepada lgeorget Hauke Lagingdan Gregory MOUSSATtelah berpartisipasi dalam jawaban ini.
Jatuh bebas untuk menambahkan detail.

SCHITS Bertrand
sumber
Saya sudah mencoba tetapi masalahnya adalah bahwa UDP-LISTEN akan menutup soket setelah paket pertama tiba, tidak peduli garpu. Gunakan UDP-RECV sebagai gantinya.
lgeorget
Tidak masalah di sini. Anda menggunakan opsi "garpu"? Saya melihat pada pria paket UDP-RECV menggabungkan. Saya tidak tahu apa artinya. UDP-RECVFROM tidak menunjukkan perilaku ini, tetapi mungkin ada kesalahan pada pria itu.
Bertrand SCHIT
Ya, saya menggunakan 'garpu'. Saya mencoba dengan socat dan dua proses netcat (satu untuk mengirim paket ke socat, yang lain untuk menerima paket siaran). Dengan UPD-LISTEN, socat mensimulasikan koneksi, dan menutup soket di ujungnya. Dengan UDP-RECV, ia menggunakan perilaku default-less UDP. Dari socat man: "Biasanya, koneksi soket akan diakhiri dengan shutdown (2) yang mengakhiri soket bahkan jika itu dibagi oleh beberapa proses."
lgeorget
2
Apakah socat akan disiarkan di semua antarmuka?
Hauke ​​Laging
1
@ lgeorget: "echo 'dummy' | nc -u -q 0 127.0.0.1 1234" berfungsi sempurna dengan -UDP-LISTEN. Saya bisa menjalankannya beberapa kali. Tapi saya punya masalah dengan -UDP-RECV dan -UDP-RECVFROM: paket-paket disiarkan pada kecepatan tautan maksimum sampai socat terbunuh. Apakah Anda melihat masalah yang sama dengan tcpdump?
Bertrand SCHIT
3

Lalu lintas siaran menurut definisi diperuntukkan bagi mesin lokal. Ini berarti paket mendapatkan DNAT'ed ke 192.168.0.255 dan kemudian kernel melihat paket dan memutuskan bahwa itu ditakdirkan untuk router itu sendiri, sehingga Anda akan melihat paket ini dalam rantai INPUT. Router (dan perangkat lainnya) akan berpikir bahwa paket 192.168.0.255 ditujukan untuk dirinya sendiri dan tidak akan meneruskannya lebih lanjut. Paket siaran tidak dialihkan / diteruskan oleh desain.

Ada solusi hebat dengan trik ARP yang disebutkan. Anda akan "kehilangan" satu alamat IP. Saya akan menggunakan dummy 192.168.0.254dalam contoh ini - ingatlah untuk tidak pernah menetapkan 192.168.0.254ke perangkat apa pun di jaringan Anda:

  1. Buat entri ARP statis pada antarmuka LAN untuk alamat IP yang tidak akan pernah Anda gunakan untuk mesin apa pun:

    arp -i ethLAN --set 192.168.0.254 FF:FF:FF:FF:FF:FF
    
  2. DNAT taffic UDP Wake-On-Lan Anda pada antarmuka WAN ke alamat IP dummy ini:

    iptables --table nat --append PREROUTING  --in-interface ethWAN --protocol udp --destination-port 1234 --jump DNAT --to-destination 192.168.0.254
    

Ini berfungsi sempurna untuk paket WOL. Solusi ini juga berfungsi pada produk yang didasarkan pada kernel Linux, seperti perangkat Mikrotik dan perangkat openwrt. Saya menggunakan trik ini pada perangkat Mikrotik untuk membangunkan mesin saya dari jarak jauh dengan ponsel saya.

plagiat0r
sumber
Paket yang diterima dari internet tidak disiarkan. Inilah sebabnya mengapa pertanyaannya adalah "Ubah UNICAST ke BROADCAST"
Gregory MOUSSAT
2

Saya menemukan pertanyaan ini di Serverfault .

Saya tidak berhasil mendapatkan lalu lintas siaran seperti itu melalui router saya. Paket-paket DNATted bahkan tidak sampai di rantai FORWARD saya. Mungkin ada beberapa opsi kernel aneh yang melarang itu.

Tapi ide ARP menarik. Saya kira itu harus disertai dengan aturan dalam OUTPUT yang melarang paket ke alamat ini sehingga hanya dapat dicapai dengan lalu lintas yang diteruskan.

Hauke ​​Laging
sumber
1

OpenWRT Socat

Socat telah dinyatakan sebagai jawaban, namun jawaban yang dinyatakan tidak bekerja untuk saya di platform saya, OpenWRT, dengan alamat WAN yang dinamis.

Tujuan saya adalah untuk meneruskan paket wake-on-lan UDP unicast dari port UDP 9 dari antarmuka WAN ke siaran subnet pada 192.168.20.255.

Yang rusak (iptables)

Saya juga mencoba dengan iptables, tetapi setiap kali saya menambahkan aturan yang berakhir pada 255, aturan tersebut berubah menjadi bubur dengan alamat tujuan 0.0.0.0 ketika saya mencetak dengan:

iptables -t nat -L

Saya percaya iptables tidak dapat melakukan multiplexing traffic, seperti yang disyaratkan dalam konversi unicast untuk menyiarkan.

Yang buruk (entri arp palsu)

Memalsukan entri arp tidak terlalu buruk, karena paket dapat diakses semua orang di segmen ethernet, tetapi memiliki kelemahan sebagai berikut

  • Anda "mengonsumsi" alamat IP
  • IP tujuan dalam paket WoL salah, meskipun Anda mendapatkannya karena alamat MAC semuanya FFFF ...
  • Kerusakan IP dapat terjadi jika seseorang di jaringan menggunakan alamat IP itu.
  • Ini adalah siaran Ethernet, dan bukan siaran IP.

Catatan: Ini dapat dilakukan dengan arpperintah atau ip neighperintah.

Yang baik

socat, seperti yang ditunjukkan oleh jawaban sebelumnya, adalah badass. Namun, jawaban socat sebelumnya, saya mengalami beberapa masalah dengannya.

  1. Socat saya tidak meneruskan lalu lintas ketika tujuan siaran UDP adalah 255.255.255.255. Saya menghindari ini dengan membatasi subnet siaran ke yang saya gunakan mungkin lebih aman.
  2. Ketika saya mengatur alamat bind ke 0.0.0.0, saya mengalami badai siaran karena lalu lintas memantul kembali ke socat dari LAN saya. Saya pertama kali memecahkan ini dengan mengikat ke publik ddns saya, namun ini tidak ideal karena ddns mungkin tidak tersedia dan alamat IP saya yang ditugaskan secara dinamis perubahan saya.

Saya dapat mengikat ke 0.0.0.0 (semua alamat) dan menghindari badai siaran dengan menambahkan aturan iptables untuk memblokir siaran masuk memantul kembali ke socat dari sisi LAN. Aturan ini, selain aturan iptables untuk menerima lalu lintas di port UDP 9, dan aturan iptables untuk mencatatnya, kami mendapatkan tiga aturan berikut selain perintah socat.

iptables -I input_wan_rule -p udp --dport 9 -j ACCEPT -m comment --comment "firewall entry to allow udp port 9 to socat"
iptables -I input_wan_rule -p udp --dport 9 -j LOG --log-prefix 'Received MAGIC PACKET on udp/9'
iptables -I input_lan_rule -p udp --dport 9 -d 192.168.20.0/24 -j DROP -m comment --comment "block broadcast from bouncing back to socat to avoid storm"

killall socat 2>/dev/null
socat -u -T1 UDP-LISTEN:9,bind=0.0.0.0,fork UDP-DATAGRAM:192.168.20.255:9,broadcast &

Untuk OpenWRTers, menempelkan ini ke dalam /etc/firewall.userdan mengeluarkan /etc/init.d/firewall restartsudah cukup.

Selamat, Anda sekarang seharusnya memiliki WoL yang bekerja untuk jaringan Anda dari mana saja di web.

vittorio88
sumber
0

Sebenarnya netfilter tidak dapat melakukan siaran apa pun, mekanisme routing melakukan ini.

Tetapi secara default ia menjatuhkan siaran yang diteruskan.

Menjadi mungkin untuk meneruskan siaran UDP yang diarahkan pada kernel Linux terbaru (sekitar versi 5.0)

Anda perlu mengubah bc_forwardingparameter untuk antarmuka jaringan penyiaran:

sudo sysctl -w net.ipv4.conf.eth1.bc_forwarding=1

(Catatan: sepertinya opsi net.ipv4.conf. Semua .bc_forwarding tidak berfungsi)

Jadi sekarang, kernel sekitar 5.0 + iptables sudah cukup untuk Anda

Yury Pavlov
sumber